为什么基类的构造函数首先调用?

时间:2017-07-16 13:02:11

标签: c++ oop inheritance

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

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

1 个答案:

答案 0 :(得分:4)

继承表示&#34; is-a&#34;关系,以便类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,这正是应该做的(除非我犯了任何错误)。这是一个完全合理的(如果有点做作的)事情。

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

总而言之,在构造任何Derived对象时,C ++必须首先将其构造为Base对象,因为Derived是一个Base并且通常依赖于它{&#} 39;实施和数据。

当你这样做时

base* b = d;

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

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