如果构造函数不是继承的话,为什么会被调用?

时间:2016-12-29 16:39:00

标签: c++ oop inheritance multiple-inheritance

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

调用构造函数
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;
}

7 个答案:

答案 0 :(得分:5)

当您阅读的文档说构造函数是&#34;没有继承&#34;时,如果类A定义构造函数A::A(int x),那么子类{{1} }不会自动拥有一个带B的构造函数。

但是,仍然需要初始化父类的值;否则,父对象可能处于无效状态。构造函数用于初始化类,因此意味着父类的一个&#39;必须从子构造函数的初始化列表中调用构造函数 。如果父类具有默认构造函数,则默认情况下会调用该构造函数。这就是你在你的例子中看到的。如果父级没有提供默认构造函数,则必须指定要调用的构造函数:

int

答案 1 :(得分:2)

  

我读到当我们从另一个类

派生一个类时,构造函数不会被继承

这是正确的。但是,你似乎误解了它的含义。

假设你有:

struct A
{
   A(int) {}
};

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

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

B b(10);

由于A(int)未继承B

这是你误解的关键。

  

那么为什么c的创建是从b和a

调用构造函数

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

有几种方法可以初始化A - B的一部分。

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

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

    B() {}
    

    这相当于:

    B() : A() {}
    

    在我提供的示例中,由于提供了另一个与默认构造函数不同的构造函数,因此删除了A的默认构造函数,因此会导致编译器错误。

  3. 回到C的默认构造函数的实现,你有:

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

    这相当于

    C() : B(), A() { cout << "C's constructor called" << endl; }
    
    构建B::B()的实例时会调用

    A::A()C

答案 2 :(得分:0)

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

课程是继承的。

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

当你从第二个类继承一个类时,构造第一个类也需要构造第二个类。因为第一个类总是包含第二个类。另一个硬性规则,没有例外。那是什么&#34;继承&#34;装置

因此,构造第一个类将调用其构造函数。然后,为了构造第二个类,它的构造函数也需要被调用(实际上第二个类首先被构造,然后第一个类的构造发生)。

这就是为什么两个构造函数都会被使用的原因。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

&#34;构造函数不是继承的&#34;意味着,C类应该并且将拥有它自己的构造函数,尽管事实上有B的构造函数,它将无法使用B的构造函数而不是C的构造函数。 这正是你得到的:你得到了所有父类的构造函数。

当你有一个类的层次结构,并从一个构造对象时,将从基础开始顺序构建所有父母。

当你将他们摧毁时,他和他所有的父母将会从他身上开始连续毁灭。

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

答案 5 :(得分:0)

通过不继承,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声明而将作为对象初始化的一部分进行调用。

答案 6 :(得分:0)

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类部分。因此,为了构造C类,我们需要通过调用这些部分的构造函数来构造它的每个部分。这些构造函数的顺序是从最基类到最派生类(在本例中为A到C)。 Most-base是继承树顶部的类,而派生最多的是底层的类。

同样的规则也适用于析构函数。唯一的区别是,从大多数派生到大多数派遣(C到A)都会调用派遣者。