我现在知道在创建对象时调用构造函数。我也知道它不可能创建一个抽象类的对象。
但是当我运行这段代码时,我会看到以下内容: -
#include <iostream>
using namespace std;
class Pet {
public:
Pet(){cout<<"in base constructor\n";}
virtual ~Pet() = 0; //making pet abstract by making drstructor pure virtual
};
Pet::~Pet() {
cout << "~Pet()" << endl;
}
class Dog : public Pet {
public:
Dog(){cout<<"in drvd constructor\n";}
~Dog() {
cout << "~Dog()" << endl;
}
};
int main() {
Pet* p = new Dog; // Upcast
delete p; // Virtual destructor call
return 0;
}
编译并运行时,其输出为: -
in base constructor
in drvd constructor
~Dog()
~Pet()
为什么Pet的构造函数被调用,即使它是一个抽象类而且不允许创建对象?所以它归结为最终是仅在对象创建的情况下调用的构造函数?
答案 0 :(得分:6)
无法创建抽象类的对象
请勿使用此广告。 您无法创建实际类型为抽象的对象。
但是,如果您实现该类(扩展它并在其中实现所有纯虚方法)并实例化新类,则将创建原始抽象基类的对象作为新类的一部分。
继承是is-a
关系。 Dog
是Pet
。创建Dog
时,您需要创建Pet
。但是你不能自己创建Pet
。
答案 1 :(得分:2)
正确的说法是“不可能创建抽象类的派生最多的对象”。但是对象也可以是更多派生对象的基础子对象,在这种情况下它们仍然需要构造。
(对象可以是三种方式的子对象:类型对象的成员子对象,派生类型对象的基础子对象或数组的元素。)
答案 2 :(得分:1)
在您的示例中,您可以创建Dog的实例,但不能创建Pet。即
Pet p; //Not possible, as destructor is abstract.
Dog d; //Allowed, because you derived from pet and ~pet( ) is defined.
一般顺序是,如果您创建目标类的对象,则按基类的顺序调用构造函数 - &gt;儿童等级 - &gt; ... - &gt;目标类。析构函数遵循相反的顺序。
为了使其可视化,请考虑目标类是其所有父类/ es的超集。 在这里,狗是一套超级宠物。