C++ 毁灭者无法解释的行为
在这个问题上: 最上面的答案有以下注释:C++ 毁灭者无法解释的行为,c++,destructor,C++,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() {
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;
}
这似乎与注释不符
我的问题是,如何在需要运行多个析构函数的类层次结构中安全地实现析构函数
例如,假设类A和类C都在堆上分配了一个属性,并且需要清理它们。我如何安全地编写这样的层次结构?注意:我目前没有尝试编写这样的层次结构,请不要回答“不要,这是糟糕的设计”。另外,我知道智能指针可以解决这个问题,这更多是为了确保我了解底层机制
它是否要求C类正确清理A类属性?如果该财产是私有的,而不是受保护的或公共的,会发生什么?我是否错过了什么,或者误解了我所看到的
用于运行这些测试的编译器
gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
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;
}
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;
}
改为:
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;
}
A类{
公众:
虚拟~A(){
std::cout更改为:
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;
}
A类{
公众:
虚拟~A(){
std::cout您在这里所指的行为是派生类中的虚拟析构函数的行为,即继承其他类的类
还记得使用C++来编译C++。
这里所指的行为是派生类中虚析构函数的行为,意思是继承其他类的类。
还记得使用C++来编译C++。
正如其他人所注意到的,你希望(需要,真的)使用继承。< /P>
他们没有注意到的是,编译器只允许你这样做,因为你在一个不应该使用的地方使用了强制转换。如果你需要使用强制转换,你真的应该坐下来,仔细考虑为什么强制转换是必要的,并且确保它所做的事情是你真正想要做的
如果没有强制转换,编译器将阻止编译损坏的代码。更正继承后,没有强制转换也可以:
#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;
}
正如其他人所指出的,您希望(实际上需要)在这里使用继承
他们没有注意到的是,编译器只允许你这样做,因为你在一个不应该使用的地方使用了强制转换。如果你需要使用强制转换,你真的应该坐下来,仔细考虑为什么强制转换是必要的,并且确保它所做的事情是你真正想要做的
如果没有强制转换,编译器将阻止编译损坏的代码。更正继承后,没有强制转换也可以:
#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不是从A派生的,因此,你的类型是david\u hero\u cast(pc)
你忘了让你的类彼此派生!继承在哪里?大多数情况下,程序执行你键入的内容,而不是你想要的内容!C不是从A派生的,因此,你的演员阵容是某种类型的david\u hero\u cast(pc)我想,我不知道我是怎么错过的,我做的事情太多了。我会尽快标记为接受。强制转换可能是危险的,派生的pTrto to > BaseTPTR强制转换是允许的,因为C++的语言没有继承任何继承,但其他转换需要明确的动作。(和你的情况一样)我想说,我不知道我是怎么错过的。我想,做一件事情太多了。我会尽快地接受。投的可能是危险的,派生的pTrto to > BaseTPTR铸件是允许的C++语言,没有任何明确的铸造,因为继承它们,但其他转换需要明确的行动。(就像你的情况一样)你是对的,我只是突然来到控制台输入完整性信息,没有太多考虑:)你是对的,我只是突然来到控制台输入完整性信息,没有太多考虑:)虽然这解决了问题,但没有解释为什么。是什么让你认为C
应该从B
继承而不是直接从A
继承?虽然这解决了问题,但没有解释为什么。是什么让你认为C
应该从B
继承而不是直接从A
继承?从技术上讲,这是一个问题e cast很好(这是一个重新解释\u cast
),删除不是。这就是为什么我在执行删除行时写了“它将触发”。虽然可能不清楚,但我会在中编辑它,感谢技术上,该cast很好(这是重新解释\u cast
),删除不是。这就是我写“它将触发”的原因,一旦删除行被执行。但可能不清楚,我将在中编辑此内容,谢谢