【发布时间】:2011-04-23 10:00:17
【问题描述】:
假设我有两个类:
class Base{};
class Derived: public Base{};
没有 d'tor,在这种情况下,如果我声明变量:
Base b;
Derived d;
我的编译器会为我生成 d'tors,我的问题是,b and d 的默认 d'tors 是否是虚拟的?
【问题讨论】:
标签: c++ destructor
假设我有两个类:
class Base{};
class Derived: public Base{};
没有 d'tor,在这种情况下,如果我声明变量:
Base b;
Derived d;
我的编译器会为我生成 d'tors,我的问题是,b and d 的默认 d'tors 是否是虚拟的?
【问题讨论】:
标签: c++ destructor
我的问题是,b 和 d 的 d'tors 是否是虚拟的
不,他们不会。如果你想要一个虚拟析构函数,你必须定义你自己的,即使它的实现与编译器提供的完全一样:
class Base {
public:
virtual ~Base() {}
};
【讨论】:
Base 和 Derived 的析构函数不会是 virtual。要创建 virtual 析构函数,您需要明确标记它:
struct Base
{
virtual ~Base() {}
};
实际上,现在使用虚拟析构函数只有一个原因。那就是关闭gcc警告:“类'Base'具有虚函数但非虚析构函数”。只要您始终将分配的对象存储在shared_ptr 中,那么您就真的不需要虚拟析构函数。方法如下:
#include <iostream> // cout, endl
#include <memory> // shared_ptr
#include <string> // string
struct Base
{
virtual std::string GetName() const = 0;
};
class Concrete : public Base
{
std::string GetName() const
{
return "Concrete";
}
};
int main()
{
std::shared_ptr<Base> b(new Concrete);
std::cout << b->GetName() << std::endl;
}
shared_ptr 将正确清理,无需虚拟析构函数。请记住,您将需要使用shared_ptr!
祝你好运!
【讨论】:
shared_ptr 或等效项。不尝试管理它们的使用方式的类更加通用。为这样的类提供一个虚拟析构函数可以在更多情况下正确使用它,而无需额外的成本。在这种情况下,用户通常不会收到有关错误使用的警告。类应该易于正确使用。
Base* pBase = new Concrete; shared_ptr<Base> shpBase(pBase); 很危险是对的,但这是丹尼尔的观点的一部分。他只是说shared_ptr<Base> shpBase(new Concrete); 并不危险,但事实并非如此,因为shared_ptr 的构造函数模板。
我的问题是,b 和 d 的 d'tors 是否是虚拟的
简短回答:不!
【讨论】:
它们不会是虚拟的。但是,如果您在 Base 中声明(并定义)了一个虚拟 dtor,那么派生的 dtor 将自动是虚拟的。 HTH。
【讨论】:
除非你明确地将它们设为虚拟,否则它们怎么可能是虚拟的
【讨论】:
只是为了给Daniel Lidström's answer添加一个例子
As long as you always store your allocated objects in a shared_ptr, then you really don't need a virtual destructor.
如果有人像这样使用 shared_ptr:
std::shared_ptr<Base> b(new Concrete);
然后在销毁对象时调用具体析构函数和基础析构函数。
如果有人像这样使用 shared_ptr:
Base* pBase = new Concrete;
std::shared_ptr<Base> b(pBase);
然后在销毁对象时只调用 Base 析构函数。
#include <iostream> // cout, endl
#include <memory> // shared_ptr
#include <string> // string
struct Base
{
virtual std::string GetName() const = 0;
~Base() { std::cout << "~Base\n"; }
};
struct Concrete : public Base
{
std::string GetName() const
{
return "Concrete";
}
~Concrete() { std::cout << "~Concrete\n"; }
};
int main()
{
{
std::cout << "test 1\n";
std::shared_ptr<Base> b(new Concrete);
std::cout << b->GetName() << std::endl;
}
{
std::cout << "test 2\n";
Base* pBase = new Concrete;
std::shared_ptr<Base> b(pBase);
std::cout << b->GetName() << std::endl;
}
}
【讨论】: