我一直在继承练习,我发现从基类指针指向继承类的deStuructor,结果为一个奇怪的输出,我发现我的destructor执行更多时间比应该。恢复我的代码(编辑:要求更多代码(:
#include <iostream>
using namespace std;
class B{
public:
virtual void f(){cout << "f() - B" << endl;}
virtual void g(){cout << "g() - B" << endl;}
virtual void h() = 0;
virtual ~B(){cout << "~B() destructor" << endl;}
protected:
int b;
};
class D1: virtual public B{
public:
void f(){cout << "f() - D1" << endl;}
virtual void g(){cout << "g() - D1" << endl;}
virtual ~D1(){cout << "~D1() destructor" << endl;}
protected:
int d1;
};
class D2: virtual public B{
public:
void f(int i){cout << "f(" << i << ") - D2" << endl;}
virtual void h(){cout << "h() - D2" << endl;}
virtual ~D2(){cout << "~D2() destructor" << endl;}
protected:
int d2;
};
class D3: public D1{
public:
void g(){cout << "g() - D3" << endl;}
void h(){cout << "h() - D3" << endl;}
private:
int d3;
};
class D4: public D1, public D2{
public:
using D1::f; using D2::f;
virtual ~D4(){cout << "~D4() destructor" << endl;}
private:
int d4;
};
void f(B& b){
cout << "f() out " << endl;
b.f();
b.g();
b.h();
};
int main()
{
B *pB;
D2 d2;
D3 d3;
D4 d4;
f(d2);
f(d3);
f(d4);
d4.D1::f();
d4.f(5);
d4.f(3.7);
d4.g();
d4.h();
pB = new D4;
pB -> f();
dynamic_cast<D4*>(pB)->f(3);
pB -> g();
pB -> h();
delete pB;
}
最终输出是:
//Other tests
.
.
.
f(3) - D2
~D4() destructor
~D2() destructor
~D1() destructor
~B() destructor
~D4() destructor
~D2() destructor
~D1() destructor
~B() destructor
~D1() destructor
~B() destructor
~D2() destructor
~B() destructor
创建PB指针;指向新的D4对象;向D4 F((方法和删除呼叫的明确调用。我期望只有四个destructor
呼叫;每个继承的类( d4,d2,d1 (,最后一个用于基类( b (。
这些结果应该正常吗?我的代码有问题吗?
您提供的代码分解以下输出:
f(3) - D2
~D4() destructor
~D2() destructor
~D1() destructor
~B() destructor
实时演示
您可以期待4个Destructor呼叫。~D4()->~D2()->~D1()->~B()
但是从输出来判断,您实际上删除了两个D4
对象,一个D1
对象和另一个D2
对象。
更新:
时称为击曲率- 您在对象上调用删除。
- 它不在范围内。
现在说明我的观点,我将介绍一个自定义范围:
int main()
{
B *pB;
{ // custom scope
D2 d2;
D3 d3;
D4 d4;
f(d2);
f(d3);
f(d4);
d4.D1::f();
d4.f(5);
d4.f(3.7);
d4.g();
d4.h();
pB = new D4;
pB->f();
dynamic_cast<D4*>(pB)->f(3);
pB->g();
pB->h();
}
delete pB;
}
调用此功能将打印以下输出:
//function calls
~D4() destructor <-- inside custom scope
~D2() destructor <-- inside custom scope
~D1() destructor <-- inside custom scope
~B() destructor <-- inside custom scope
~D1() destructor <-- inside custom scope
~B() destructor <-- inside custom scope
~D2() destructor <-- inside custom scope
~B() destructor <-- inside custom scope
~D4() destructor <-- outside custom scope
~D2() destructor <-- outside custom scope
~D1() destructor <-- outside custom scope
~B() destructor <-- outside custom scope
您的 D2
, D3
和 D4
对象分配在堆栈上,而分配在堆上的 D4
对象。您正在看到D1
,D2
和D4
驱动器的输出(您没有在D3
Destructor中输出任何内容(。
您认为delete
是灾难仪被调用的唯一方法吗?事实并非如此,但这似乎就是您在想的。您将为您创建的所有4个对象获取破坏者的输出消息。堆栈上的对象在main()
的末端出现范围时会自动破坏(以相反的创建顺序(。当您在其上明确调用delete
时,堆上的对象会破坏:
// when you delete pB...
~D4() destructor
~D2() destructor
~D1() destructor
~B() destructor
// when d4 goes out of scope...
~D4() destructor
~D2() destructor
~D1() destructor
~B() destructor
// when d3 goes out of scope...
~D1() destructor
~B() destructor
// when d2 goes out of scope...
~D2() destructor
~B() destructor
请参阅此实时演示,它具有与您显示的相同的驱动器输出。
如果您将输出添加到D3
的destructor:
class D3: public D1{
public:
void g(){cout << "g() - D3" << endl;}
void h(){cout << "h() - D3" << endl;}
virtual ~D3(){cout << "~D3() destructor" << endl;} // <-- add this!
private:
int d3;
};
// when d3 goes out of scope...
~D3() destructor <-- this message now appears
~D1() destructor
~B() destructor