【问题标题】:why constructor of base class invokes first? [duplicate]为什么基类的构造函数首先调用? [复制]
【发布时间】:2017-12-21 02:03:18
【问题描述】:

在运行下面的代码时,为什么我们先声明了派生类的对象,还是先派生了基类的构造函数。

#include<iostream>

using namespace std;

class base {
  public:
    base()
    { cout<<"Constructing base \n"; }
    ~base()
    { cout<<"Destructing base \n"; }
};

class derived: public base {
  public:
    derived()
    { cout<<"Constructing derived \n"; }
    ~derived()
    { cout<<"Destructing derived \n"; }
};

int main(void)
{
  derived *d = new derived(); //d is defined ahead of the base class object
  base *b = d;
  delete b;

  return 0;
}

【问题讨论】:

  • 您还能期待什么?为什么?
  • 提示:derived 内部有一个base 子对象
  • 对象是自下而上构造的。 derived 有一个base 类型的基类,因此当您创建derived 的实例时,您会看到一系列构造函数调用,例如:base -> derived。您如何在墙壁尚未到位的房屋上安装屋顶?自下而上。就是这样。
  • 请查看类数据初始化规则here
  • @samfisher 它打印 constructing base 然后 constructing derived,因为你必须首先初始化一个 base 对象如果你想创建一个derived 的话。前者是后者的子对象。

标签: c++ oop inheritance


【解决方案1】:

继承表达了一种“is-a”关系,所以derived类的所有对象都是base类的对象。 derived 对象具有 base 对象所做的所有数据和方法,以及在 derived 类声明中显式声明的数据和方法。

完全有可能(并且很常见)编写 Derived 类,这些类依赖于它们的 Base 类的实现。例如,假设我们有

class Base {
public:
    Base() { n = 5; }
    int GetN() const { return n; }
private:
    int n;
};

class Derived : public Base {
public:
    Derived() { m = GetN() * 2; }
    int GetM() const { return m; }
private:
    int m;
};

现在我们期待

Derived* d = new Derived();
std::cout << d->GetM() << std::endl;

打印10,这正是它应该做的(除非我有任何错误)。这是一件完全合理(如果有点做作)的事情。

当构造Derived 类型的对象时,语言可以使这样的代码正常工作的唯一方法是在Derived 构造函数之前运行Base 构造函数。这是因为Derived 构造函数依赖于能够调用GetN() 方法,该方法继承自Base,其正常运行取决于数据成员n 已在Base 中正确初始化构造函数。

总而言之,在构造任何Derived 对象时,C++ 必须首先将其构造为Base 对象,因为Derived 是一个Base,并且通常取决于它的实现和数据。

当你这样做时

base* b = d;

在您的代码中,您声明了一个类型为“指向base 对象的指针”的变量b,然后使用d 中保存的相同内存地址初始化此变量。编译器不介意您这样做,因为所有derived 对象都是base 对象,因此您可能希望将d 视为b 是有道理的。但是,这里的对象实际上并没有发生任何事情,它只是一个指针变量的声明和实例化。 d 指向的对象已经是base 对象,因为所有derived 对象都是基础对象。

请注意,这种解释是故意使边缘有点模糊,并且远没有完全解释 C++ 中基类和派生类之间的关系。你会想去查看其他文章/书籍/标准。我希望这对初学者来说相对容易理解。

【讨论】:

    猜你喜欢
    • 2012-05-19
    • 1970-01-01
    • 2013-01-28
    • 2012-02-28
    • 2010-09-13
    • 2020-03-17
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    相关资源
    最近更新 更多