如果未继承,为什么要调用构造函数

why constructors are called if they are not inherited?

本文关键字:调用 构造函数 为什么 继承 如果      更新时间:2023-10-16

代码正在打印所有构造函数。我读到,当我们从另一个类得出类时,构造函数并未继承。那么为什么创建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;
}

当您读取的文档所述构造函数是"未继承"时,这意味着如果类A定义了构造函数A::A(int x),则儿童类B将不会自动有一个采用int的构造函数。

但是,仍然有必要初始化父类的值。否则,父对象可能处于无效状态。构造函数用于初始化类,因此,含义是父级构造函数的必须从子构建体的 initializer list 中调用。如果父类具有默认构造函数,则默认情况下会调用。这就是您在示例中看到的。如果父母不提供默认构造函数,则必须指定要称为哪个:

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; }
};

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

类是继承的。

,但是要构建一个类,需要调用其构造函数。那是它的工作。硬规则,没有例外。

当您从第二类继承一个类时,构建第一类也需要构建第二类。因为第一类总是包含第二类。另一个艰难的规则,没有例外。这就是"继承"的含义。

因此,构建头等舱将调用其构造函数。然后,要构建第二类,也需要调用其构造函数(实际上第二类首先构造,然后进行第一类的构造)。

这就是为什么两个构造函数都将被使用。

我读到当我们从其他类得出类时,构造函数不是继承的

那是正确的。但是,您似乎误解了这一点的含义。

假设您有:

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

给定上述,您将无法使用:

B b(10);

因为A(int)未继承B

那是您误会的关键。

那么,为什么C的创建是从B和A

调用构造函数的

但是,当您构造B时,B的构造函数被调用以初始化其成员。还必须调用A的构造函数,以便可以初始化与A相对应的B的子对象。

有几种方法可以初始化AB

的部分
  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的实例时调用。

构造函数在classens 在继承时。继承基本上给出了基本类的派生类实例匿名成员实例,以及其他事项。这些实例需要构造以使其构造函数称为。

"构造函数不是继承的"意味着,C类应该并且将拥有自己的构造函数,尽管有B的构造函数,但它将无法使用B的构造函数而不是C的构造函数。这正是您得到的:您将获得所有父级的构造函数。

当您拥有课堂的层次结构并从一个构建对象时,他的所有父母将从基础上开始。

当您将它们摧毁时,将从他开始,他和他所有的父母会造成顺序破坏。

按规则:首次创建 - 最后破坏。

否未继承,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;
};

在您的情况下,您正在定义所有默认ctors,并且是否明确定义,仍然存在,并且由于您的C c声明而将其称为对象初始化的一部分。

c 继承基本上创建了由其超级类别的部分组成的类。例如:

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';
        }
};

C类实际上是C类,带有B类部分和A类A零件。因此,为了构建C类,我们需要通过调用这些部分的构造函数来构造其每个部分。这些构造函数的顺序是从最基本的类到最衍生的类(在这种情况下为a至c)。最大的是继承树顶部的班级,最衍生的是底部的班级。

同样的规则也适用于破坏者。唯一的区别是,从大多数衍生到大多数基础(c至a)的驱动器被调用。