为什么我的C++子类需要一个显式构造函数?

12

我有一个基类,它声明和定义了一个构造函数,但出于某些原因,我的公共派生类没有看到那个构造函数,因此我不得不在派生类中明确声明一个转发构造函数:

class WireCount0 {
protected:
    int m;
public:
    WireCount0(const int& rhs) { m = rhs; }
};

class WireCount1 : public WireCount0 {};

class WireCount2 : public WireCount0 {
public: 
  WireCount2(const int& rhs) : WireCount0(rhs) {}
};

int dummy(int argc, char* argv[]) {
    WireCount0 wireCount0(100);
    WireCount1 wireCount1(100);
    WireCount2 wireCount2(100);
    return 0;
}
在上述代码中,我的WireCount1 wireCount1(100)声明被编译器拒绝("No matching function for call to 'WireCount1::WireCount1(int)'),而我的wireCount0wireCount2声明则是正确的。
我不确定为什么需要提供WireCount2中所示的显式构造函数。是因为编译器为WireCount1生成了一个默认构造函数,而该构造函数隐藏了WireCount0构造函数吗?
参考文献:编译器为i686-apple-darwin10-gcc-4.2.1(GCC)4.2.1(Apple Inc. build 5659)
3个回答

15

构造函数是不会被继承的。您需要为派生类创建一个构造函数。派生类的构造函数必须调用基类的构造函数。


1
另外,如果基类有一个默认构造函数,则编译器将在派生类的构造函数初始化列表中未显式指定构造函数时使用该构造函数。 - In silico
谢谢。我没有意识到构造函数永远不会被继承。我曾经相信其他基类构造函数(在实际代码中)实际上是可见的,但现在我认为这归因于编译器可能进行的大量转换。 - Neil Steiner
很抱歉,作为一名新手,我还没有足够的声望点数来提升您的答案。 - Neil Steiner
1
我本以为可以早点回家...现在却要加班,填写子类中完全相同的代码行。 - Jonny

9
所有派生类都必须以某种方式调用其基类的构造函数。
当您创建一个重载构造函数时,您的默认编译器生成的无参数构造函数将消失,并且派生类必须调用重载构造函数。
当您有以下代码时:
class Class0 {
}

class Class1 : public Class0 {
}

编译器实际上生成了这个内容:
class Class0 {
public:
  Class0(){}
}

class Class1 : public Class0 {
  Class1() : Class0(){}
}

当你有非默认构造函数时,无参构造函数将不再生成。当你定义如下内容:

class Class0 {
public:
  Class0(int param){}
}

class Class1 : public Class0 {
}

编译器不再为Class1生成调用基类构造函数的构造函数,您必须自己显式地执行该操作。

我认为你误读了他的问题。他不是在问为什么他不能调用Class1的默认构造函数,而是为什么没有Class1(int)构造函数可以调用。 - Shirik
1
编译器在您的最后一个示例中仍会生成Class1()构造函数。只是如果它实际上被定义了(默认情况下对于所有特殊函数,它只被声明直到实际使用),则此构造函数是不完整的。您可以通过将其设置为友元来验证这一点:class Class2 { friend Class1::Class1(); };,这是有效的,因为编译器隐式声明默认构造函数,无论它是否实际上被调用。 - Johannes Schaub - litb
谢谢。这让我非常清楚。虽然我很感激Shirik的回答,但我相信你的例子恰好展示了我的代码中正在发生的事情。 - Neil Steiner
@Johannes Schaub - litb 谢谢你,我不知道那个。 - Igor Zevaka
这个问题在http://stackoverflow.com/questions/22951260/do-default-constructors-need-to-call-base-class-default-constructors/22951286#22951286 有讨论,供您参考。 - Manuel Arwed Schmidt

1

在处理派生类之前,您必须构建基类。如果您使用非平凡的构造函数构建派生类,则编译器无法决定要调用哪个基类,这就是错误发生的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接