析构函数无法解释的行为
Unexplainable behaviour of destructor
在这个问题中:虚析构函数是如何工作的?
上面的答案有以下注释:
Note that the destructor of the base class will be called implicitly after the destructor of the derived class finishes. This is a difference to the usual virtual functions.
我编写了一个快速的示例程序来测试它,
class A {
public:
virtual ~A() {
std::cout << "A DESTRUCTOR" << std::endl;
}
};
class B {
public:
virtual ~B() {
std::cout << "B DESTRUCTOR" << std::endl;
}
};
class C {
public:
virtual ~C() {
std::cout << "C DESTRUCTOR" << std::endl;
}
};
int main(int argc, char** argv)
{
A * aPtr = (A *)new C();
C * cPtr = new C();
delete aPtr;
delete cPtr;
return 0;
}
我得到的输出是
C DESTRUCTOR
C DESTRUCTOR
这似乎与注释不一致。
我的问题是,如何在需要运行多个析构函数的类层次结构中安全地实现析构函数?
例如,假设类A和类C都在堆上分配了一个属性,并且需要清理它们。如何安全地编写这样的层次结构?注意:我目前并没有试图写这样的层次结构,请不要回答"不要,这是糟糕的设计"。此外,我知道智能指针可以解决这个问题,这更多的是为了确保我理解底层机制。是否要求C类正确地清理A类属性?如果该财产是私有的,而不是受保护的或公共的,会发生什么?是我错过了什么,还是我误解了我所看到的?
用来运行这些测试的编译器
gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
正如其他人所注意到的,您希望(确实需要)在这里使用继承。
他们没有注意到的是,编译器只允许你这样做,因为你在不应该的地方使用了强制转换。如果你需要使用强制转换,你真的应该坐下来,仔细考虑为什么强制转换是必要的,并确定它所做的确实是你想做的。如果没有强制类型转换,编译器将阻止编译损坏的代码。修正了继承之后,没有强制类型转换就可以了:
#include <iostream>
class A {
public:
virtual ~A() {
std::cout << "A DESTRUCTOR" << std::endl;
}
};
class B : public A {
public:
virtual ~B() {
std::cout << "B DESTRUCTOR" << std::endl;
}
};
class C : public B {
public:
virtual ~C() {
std::cout << "C DESTRUCTOR" << std::endl;
}
};
int main(int argc, char** argv) {
A * aPtr = new C();
delete aPtr;
}
结果:C DESTRUCTOR
B DESTRUCTOR
A DESTRUCTOR
-
你忘记了类之间的继承
-
这将触发未定义的行为,只要你执行
delete
行A * aPtr = (A *)new C();
我相信这就是你要找的
class A {
public:
virtual ~A() {
std::cout << "A DESTRUCTOR" << std::endl;
}
};
class B : public A{
public:
virtual ~B() {
std::cout << "B DESTRUCTOR" << std::endl;
}
};
class C : public B{
public:
virtual ~C() {
std::cout << "C DESTRUCTOR" << std::endl;
}
};
int main(int argc, char** argv)
{
A * aPtr = new C(); // The cast here is not needed
C * cPtr = new C();
delete aPtr;
delete cPtr;
return 0;
}
输出C DESTRUCTOR
B DESTRUCTOR
A DESTRUCTOR
C DESTRUCTOR
B DESTRUCTOR
A DESTRUCTOR
改成:
class A {
public:
virtual ~A() {
std::cout << "A DESTRUCTOR" << std::endl;
}
};
class B : public A{
public:
virtual ~B() {
std::cout << "B DESTRUCTOR" << std::endl;
}
};
class C : public B{
public:
virtual ~C() {
std::cout << "C DESTRUCTOR" << std::endl;
}
};
您这里所指的行为是派生类中的虚析构函数的行为,即继承了其他类的类。
还记得在编译c++时使用g++
相关文章:
- 单例类析构函数无法清理 (SDL_Quit) MinGW
- 为什么结构与auto_ptr和显式析构函数无法交换
- 无法手动调用 std::string 的析构函数
- C++析构函数无法正确释放
- 为什么我在使用组合而不是继承时得到 C4624(无法访问基类析构函数)
- 有人可以解释一下这里发生了什么(类和构造函数/析构函数)吗?
- 无法调用其他类C++的析构函数
- 为什么无法正确分析显式析构函数调用中的限定类型名称?
- 我无法让我的析构函数在我的代码中工作
- C++基于堆栈的构造函数/析构函数无法按预期工作
- C++析构函数运行时错误:无法munmap
- 无法访问类析构函数中的联合成员
- 析构函数无法解释的行为
- C++类析构函数无法正常工作
- 如果声明析构函数,为什么此代码无法编译?
- List的析构函数无法删除最后一个节点
- C++析构函数EXC_BAD_ACCESS无法访问内存
- 无法退出,因为析构函数错误导致main()在退出时停止执行
- 请解释析构函数调用的顺序
- 无法从继承的类调用析构函数