如果构造函数不是继承的,为什么要调用它们?

why constructors are called if they are not inherited?

代码正在打印所有构造函数。我读到当我们从另一个 class 派生 class 时,构造函数不会被继承。那么为什么 c 的创建是从 ba

调用构造函数
class A
{
public:
  A()  { cout << "A's constructor called" << endl; }
};

class B
{
public:
  B()  { cout << "B's constructor called" << endl; }
};

class C: public B, public A  // Note the order
{
public:
  C()  { cout << "C's constructor called" << endl; }
};

int main()
{
    C c;
    return 0;
}

构造函数不是传统意义上的继承。

类是继承的。

但是为了构造一个class,需要调用它的构造函数。那是它的工作。硬性规定,无一例外。

当您从第二个 class 继承一个 class 时,构建第一个 class 也需要构建第二个 class。因为第一个 class 总是包含第二个 class。另一个硬性规定,没有例外。这就是 "inheritance" 的意思。

因此,构造第一个 class 将调用其构造函数。然后,要构建第二个 class,还需要调用它的构造函数(实际上是先构建第二个 class,然后再构建第一个 class)。

这就是将使用两个构造函数的原因。

构造函数在class继承时被调用。继承基本上为派生 class 实例提供基 classes 的匿名成员实例,等等。需要构造这些实例,以便调用它们的构造函数。

当您阅读的文档说构造函数是 "not inherited" 时,这意味着如果 class A 定义了一个构造函数 A::A(int x),那么子 class B 不会自动拥有一个采用 int.

的构造函数

但是,仍然需要初始化父级的值class;否则,父对象可能处于无效状态。构造函数用于初始化 classes,因此意味着 one 的父 class' 构造函数 must 从子构造函数的 初始化程序列表 。如果父 class 有默认构造函数,则默认调用该构造函数。这就是您在示例中看到的。如果父级不提供默认构造函数,则必须指定要调用的构造函数:

class A
{
public:
  A(int x)  { cout << "A's constructor called" << endl; }
};

class C: public A
{
public:
  C()  
  : A(7)  /* compilation will fail without this line */
  { cout << "C's constructor called" << endl; }
};

"Constructors are not inherited" 意味着,class C 应该并且将会有它自己的构造函数,尽管事实上有 B 的构造函数,但它不能使用 B 的构造函数而不是 B 的构造函数C。 这正是你得到的:你得到所有 parent classes.

的构造函数

当你有 class 的层次结构,并从一个构建 object 时,他的所有 parent 将按顺序构建,从基层开始。

当你摧毁它们时,他和他所有的 parent 将被依次摧毁,从他开始。

按规则:最先创建 -- 最后销毁。

通过不继承,C++11标准是这个意思

class A
{
    public: 
        A(int x) {}
};

class B: public A
{
};

int main(void)
{
    B b(5);
    return 0;
}

这将无法编译,因为 A(int) 不是继承的。您可以定义 B 以通过

显式继承 A(int)
class B: public A
{
     using A::A;
};

在您的情况下,您正在定义所有默认构造器,无论是否显式定义,它们仍然存在,并且由于您的 C c 声明,将作为对象初始化的一部分被调用。

C++ 继承基本上创建了一个 class 由它的超 class 部分组成。例如:

class A {
    public:
        A() {
            std::cout << "Constructor A" << '\n';
        }
};

class B : public A {
    public:
        B() {
            std::cout << "Constructor B" << '\n';
        }
};

class C : public B {
    public:
        C() {
            std::cout << "Constructor C" << '\n';
        }
};

Class C其实就是class C,有一个class B部分,还有一个class A部分。因此,为了构造 class C,我们需要通过调用这些部分的构造函数来构造它的每个部分。这些构造函数的顺序是从最基础的 class 到最衍生的 class(在本例中为 A 到 C)。 Most-base 是继承树顶部的 class,most-derived 是底部的 class。

同样的规则也适用于析构函数。唯一的区别是析构函数是从最派生到最基(C 到 A)调用的。

i read that constructors are not inherited when we derive a class from another class

没错。不过,你好像误解了那个意思。

假设您有:

struct A
{
   A(int) {}
};

struct B : A
{
   B() : A(0) {}
};

鉴于以上情况,您将无法使用:

B b(10);

因为 A(int) 没有被 B 继承。

这就是你误解的症结所在。

then why creation of c is invoking constructors from b and a

然而,当你构造一个B时,会调用B的构造函数来初始化它的成员。还必须调用 A 的构造函数,以便可以初始化 A 对应的 B 的子对象。

有几种方法可以初始化 BA 部分。

  1. 您可以使用语法在成员初始化列表中显式使用 A 的构造函数:

    B() : A(0) {}
    
  2. 将成员初始化留空,在这种情况下调用A的默认构造函数。

    B() {}
    

    相当于:

    B() : A() {}
    

    在我给出的示例中,这将导致编译器错误,因为 A 的默认构造函数已通过提供不同于默认构造函数的另一个构造函数被删除。

回到 C 的默认构造函数的实现,您有:

C()  { cout << "C's constructor called" << endl; }

相当于

C() : B(), A() { cout << "C's constructor called" << endl; }

B::B()A::A() 在构造 C 的实例时被调用。