从派生类调用基类构造函数的C++规则是什么?

例如,我知道在Java中,您必须作为子类构造函数的第一行执行此操作(如果不这样做,则假定对无参数超级构造函数的隐式调用-如果缺少,则会给您一个编译错误)。


当前回答

如果在基构造函数中有默认参数,则将自动调用基类。

using namespace std;

class Base
{
    public:
    Base(int a=1) : _a(a) {}

    protected:
    int _a;
};

class Derived : public Base
{
  public:
  Derived() {}

  void printit() { cout << _a << endl; }
};

int main()
{
   Derived d;
   d.printit();
   return 0;
}

输出为:1

其他回答

在C++中,在进入构造函数之前,所有超类和成员变量的无参数构造函数都会为您调用。如果要传递参数,有一个单独的语法称为“构造函数链接”,如下所示:

class Sub : public Base
{
  Sub(int x, int y)
  : Base(x), member(y)
  {
  }
  Type member;
};

如果在这一点运行的任何东西抛出,则调用先前已完成构造的基/成员的析构函数,并将异常重新抛出给调用者。如果要在链接过程中捕获异常,必须使用函数try块:

class Sub : public Base
{
  Sub(int x, int y)
  try : Base(x), member(y)
  {
    // function body goes here
  } catch(const ExceptionType &e) {
    throw kaboom();
  }
  Type member;
};

在这种形式中,请注意try块是函数的主体,而不是在函数的主体内;这允许它捕获由隐式或显式成员和基类初始化以及在函数体期间引发的异常。但是,如果函数catch块没有抛出不同的异常,则运行时将重新抛出原始错误;初始化期间的异常不能忽略。

如果基类构造函数没有参数,它们将自动为您调用。如果要使用参数调用超类构造函数,则必须使用子类的构造函数初始化列表。与Java不同,C++支持多重继承(无论好坏),因此基类必须按名称引用,而不是“super()”。

class SuperClass
{
    public:

        SuperClass(int foo)
        {
            // do something with foo
        }
};

class SubClass : public SuperClass
{
    public:

        SubClass(int foo, int bar)
        : SuperClass(foo)    // Call the superclass constructor in the subclass' initialization list.
        {
            // do something with bar
        }
};

有关构造函数初始化列表的更多信息,请点击此处。

当一个类从多个类派生时,没有人提到构造函数调用的顺序。该序列如派生类时所述。

如果在基构造函数中有默认参数,则将自动调用基类。

using namespace std;

class Base
{
    public:
    Base(int a=1) : _a(a) {}

    protected:
    int _a;
};

class Derived : public Base
{
  public:
  Derived() {}

  void printit() { cout << _a << endl; }
};

int main()
{
   Derived d;
   d.printit();
   return 0;
}

输出为:1

CDerived::CDerived()
: CBase(...), iCount(0)  //this is the initialisation list. You can initialise member variables here too. (e.g. iCount := 0)
    {
    //construct body
    }