在运行下面的代码时,为什么首先派生基类的构造函数,即使我们首先声明了一个派对类的对象。
#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;
}
答案 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 ++中基类和派生类之间的关系。你会想去寻找其他文章/书籍/标准。我希望这对于初学者来说相对容易理解。