如何调用基类构造函数?

Ste*_*fan 64 c++ constructor

我在Java中花了很多编程.你在那里调用你继承的类super();(你们都可能知道)

现在我有一个C++类,它有一个默认的构造函数,它接受一些参数.例:

class BaseClass {
public:
    BaseClass(char *name); .... 
Run Code Online (Sandbox Code Playgroud)

如果我继承了它,它会给我警告,没有适当的默认构造函数可用.那么super()在C++中有类似的东西,还是我必须定义一个初始化所有变量的函数?

Bjö*_*lex 87

您可以在子类的构造函数的初始化列表中执行此操作.

class Foo : public BaseClass {
public:
    Foo() : BaseClass("asdf") {}
};
Run Code Online (Sandbox Code Playgroud)

在初始化任何成员之前,必须在那里调用带参数的基类构造函数.

  • 好吧,为了迂腐,在初始化任何成员之前,将在初始化列表中调用基类构造函数*; 如果没有提供基类,则它会尝试隐式使用默认构造函数.如果存在`BaseClass`的默认构造函数,并且初始化列表中没有其他构造函数,则默认*将被调用; 并不是程序员**有**打电话给它. (13认同)

Mas*_*rHD 30

在头文件中定义一个基类:

class BaseClass {
public:
    BaseClass(params);
};
Run Code Online (Sandbox Code Playgroud)

然后将派生类定义为继承BaseClass:

class DerivedClass : public BaseClass {
public:
    DerivedClass(params);
};
Run Code Online (Sandbox Code Playgroud)

在源文件中定义BaseClass构造函数:

BaseClass::BaseClass(params)
{
     //Perform BaseClass initialization
}
Run Code Online (Sandbox Code Playgroud)

默认情况下,派生构造函数只调用没有参数的默认基础构造函数; 所以在这个例子中,在调用派生构造函数时不会自动调用基类构造函数,但只需在冒号(:)之后添加基类构造函数语法即可实现.定义一个自动调用其基础构造函数的派生构造函数:

DerivedClass::DerivedClass(params) : BaseClass(params)
{
     //This occurs AFTER BaseClass(params) is called first and can
     //perform additional initialization for the derived class
}
Run Code Online (Sandbox Code Playgroud)

BaseClass构造被称为BEFORE DerivedClass构造和相同/不同的参数params,如果需要,也可以转发到的基类.这可以嵌套用于更深层次的派生类.派生的构造函数必须调用EXACTLY ONE基础构造函数.析构函数是在调用构造函数的REVERSE顺序中自动调用的.

编辑:如果您从任何virtual类继承,通常是为了实现多重继承钻石继承,则此规则有一个例外.然后你必须显式调用所有virtual基类的基础构造函数并显式传递参数,否则它只会调用它们的默认构造函数而不带任何参数.请参阅:虚拟继承 - 跳过构造函数


Nic*_*las 18

你必须使用initiailzers:

class DerivedClass : public BaseClass
{
public:
  DerivedClass()
    : BaseClass(<insert arguments here>)
  {
  }
};
Run Code Online (Sandbox Code Playgroud)

这也是您构建类的没有构造函数(或者您想要初始化)的成员的方法.未提及的任何成员将被默认初始化.例如:

class DerivedClass : public BaseClass
{
public:
  DerivedClass()
    : BaseClass(<insert arguments here>)
    , nc(<insert arguments here>)
    //di will be default initialized.
  {
  }

private:
  NeedsConstructor nc;
  CanBeDefaultInit di;
};
Run Code Online (Sandbox Code Playgroud)

指定成员的顺序是无关紧要的(尽管构造函数必须首先出现),但它们将构造的顺序是声明顺序.因此nc将始终构建di.


Seb*_*fel 5

关于超级的替代方案;在大多数情况下,您可以在派生类的初始化列表中使用基类,或者在Base::someData其他地方进行工作时使用语法,并且派生类重新定义数据成员。

struct Base
{
    Base(char* name) { }
    virtual ~Base();
    int d;
};

struct Derived : Base
{
    Derived() : Base("someString") { }
    int d;
    void foo() { d = Base::d; }
};
Run Code Online (Sandbox Code Playgroud)