如何调用基类构造函数?

时间:2011-08-03 08:37:47

标签: c++ constructor

latley我在Java中花了很多编程。在那里,您使用super();调用您继承的类(您可能都知道)

现在我有一个C ++类,它有一个带有一些参数的默认构造函数。例如:

class BaseClass {
public:
    BaseClass(char *name); .... 

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

6 个答案:

答案 0 :(得分:80)

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

class Foo : public BaseClass {
public:
    Foo() : BaseClass("asdf") {}
};

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

答案 1 :(得分:27)

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

class BaseClass {
public:
    BaseClass(params);
};

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

class DerivedClass : public BaseClass {
public:
    DerivedClass(params);
};

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

BaseClass::BaseClass(params)
{
     //Perform BaseClass initialization
}

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

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

BaseClass构造函数在DerivedClass构造函数之前调用,如果需要,可以将相同/不同的参数params转发到基类。这可以嵌套用于更深层次的派生类。派生的构造函数必须调用EXACTLY ONE基础构造函数。析构函数在REVERSE命令中被AUTOMATICALLY调用,调用构造函数。

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

答案 2 :(得分:17)

你必须使用initiailzers:

class DerivedClass : public BaseClass
{
public:
  DerivedClass()
    : BaseClass(<insert arguments here>)
  {
  }
};

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

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

private:
  NeedsConstructor nc;
  CanBeDefaultInit di;
};

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

答案 3 :(得分:4)

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

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

struct Derived : Base
{
    Derived() : Base("someString") { }
    int d;
    void foo() { d = Base::d; }
};

答案 4 :(得分:3)

在初始化列表中使用基类的名称。初始化列表出现在方法体之前的构造函数签名之后,可用于初始化基类和成员。

class Base
{
public:
  Base(char* name)
  {
     // ...
  }
};

class Derived : Base
{
public:
  Derived()
    : Base("hello")
  {
      // ...
  }
};

或者,某些人使用的模式是自己定义“超级”或“基础”。也许有些喜欢这种技术的人是转向C ++的Java开发人员。

class Derived : Base
{
public:
  typedef Base super;
  Derived()
    : super("hello")
  {
      // ...
  }
};

答案 5 :(得分:2)

C ++中没有super()。您必须按名称显式调用Base Constructor。