问题描述
我现在正在学习继承,但有一件事我还没有找到可靠的答案。如果我有三个类,一个是超类,两个是子类,如果它们继承相同的字段,我的子类是否需要默认构造函数?类 b 没有默认构造函数,因为它继承了 A 的字段,而类 c 有不同的字段,因此它需要自己的默认构造函数。
class A {
private:
int a;
int b;
public:
A();
A(int,int);
};
class B: public A {
public:
B(int,int);
};
class C : public A {
private:
int c;
public:
C();
C(int,int);
};
不胜感激。
解决方法
如果您打算调用代码以便能够使用默认构造函数并创建类的实例而无需向其传递额外参数,则类应该具有默认构造函数。 B 不会因为 B 没有添加额外的成员变量而自动获得 A 的默认构造函数。
B
不会因为 A
有一个默认构造函数而自动拥有一个默认构造函数而 B
没有任何新变量。如果你想转发 A
的默认构造函数,你可以像这样使用 using declaration:
class A {
private:
int a;
int b;
public:
A();
A(int,int);
};
class B: public A {
public:
using A::A; // All of A's constructors are now publically usable as B constructors
};
请注意,我删除了声明 B(int,int);
,因为 using
声明将 both 构造函数从 A
前移。如果您希望 B(int,int);
执行与 A(int,int);
不同的操作,您可以在 B(int,int);
声明旁边声明 using
,并且派生程度更高的构造函数将隐藏继承的构造函数。
如果[无关],如果[无关],我的子类是否需要默认构造函数?
这取决于您的子类的使用方式。如果 – 且仅当 – 您需要在不提供构造参数的情况下构造类的实例,则该类需要一个默认构造函数。是否需要显式定义(或通过 using
转发)默认构造函数取决于是否定义了其他构造函数,以及该构造函数是否有重要的事情要做。早在继承之前,这个主题就应该被涵盖。
然而,当继承进入画面时,有一个新的警告。由于我无法确定您是否使用 member initialization lists,我建议您阅读 No Matching Function Call to Base class。如果您不使用成员初始化列表,您的派生类将在没有构造参数的情况下构造它们的基类。但是,请注意,通常最好使用初始化列表而不是添加默认构造函数来解决这种情况。
类 b 没有默认构造函数,因为它继承了 A 的字段,
不,类 B
没有默认构造函数,因为它定义了一个非默认构造函数。非默认构造函数可防止编译器提供默认构造函数。如果您的代码成功编译,则可以得出 B
不需要默认构造函数的结论。
由于类 c 具有不同的字段,因此它需要自己的默认构造函数。
一个类是否有字段与“需要”无关。 (字段可能使显式默认构造函数更可能更合适,因为可能有数据要初始化,但它们的存在并不意味着需要。)