带非虚析构函数的基类怎么样?
How about a base class with a non-virtual destructor?
如果在子类private中声明"operator new",可以使用没有虚析构函数的类作为基类吗?
以下代码是否会导致运行时问题:
class B {
public:
~B() { }
};
class D: public B {
private:
void* operator new(size_t);
}
无论如何在派生类中重写operator new
,您都可以使用带有非虚析构函数的类作为基类。
delete
和指向基的指针,因为这会导致未定义行为。在派生类中重写operator new
不会改变这个事实。
你仍然可以说Base * p = ::new Derived;
,从而造成危险的情况
这里有一组简单的指导原则,说明什么时候应该将析构函数设置为虚函数
http://www.parashift.com/c + + faq/virtual-dtors.html
如果你想阻止派生类的对象被构造,那么把构造函数设为私有,而不是把new
操作符设为私有。
c++语言不要求基类必须有virtual
析构函数。所以,对你的问题的直接回答是"是的",你可以有一个没有虚析构函数的基类。
但是,如果不调用未定义行为,则不能通过基类指针实例化派生对象和delete
。
class Base
{
};
class Derived
:
public Base
{
public:
std::string mString;
};
Base* p = new Derived;
delete p;
你的delete
是一个Base
指针,但是*p
的动态类型是Derived
, Base
没有virtual
析构函数,所以这调用了UB:
5.3.5/3删除
在第一个备选项(删除对象)中,如果是静态类型的操作数与其动态类型不同时,其静态类型应为a操作数的动态类型和静态类型的基类应有虚析构函数,否则行为未定义。在第二个如果对象为动态类型,则可选择(删除数组)已删除的不同于它的静态类型,行为是未定义的。73)
你也不能使用这样的诡计:
Base* p = new Derived;
Derived* d = dynamic_cast <Derived*> (p);
delete d;
…因为只有当目标是多态的(即至少有1个virtual
成员,而Base
没有),你才能用dynamic_cast
投射树。
所以,即使对你的问题的直接回答是"是",真正的答案是"不要那样做"。
虚拟医生不是基类的必要条件,您当然可以对所有已定义的结果都这样做。而且不需要使用op new之类的
与准则相关的问题案例是,在指向派生类实例的指向base的指针上使用delete。
如果您的设计确保删除不会以这种方式发生,则可以继续执行。尽管正确地记录这一点是一个好主意,这样未来的开发人员就不会急于"修复"这种情况,或者不违反规则。
- std::具有相同基类的类的变体
- 是否可以初始化不可复制类型的成员变量(或基类)
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 基类中的函数名称解析
- C++初始化基类
- 如何通过派生类函数更改基类中的向量
- 如何定义一个纯抽象基类
- 如何使用基类指针引用派生类成员
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 使用基类指针创建对象时,缺少派生类析构函数
- 如何引用基类的派生类?
- 如果基类包含双指针成员,则派生类的构造函数
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 为什么此派生对象无法访问基类的后递减方法?
- 公开最直接的基类模板名称
- 当基类是依赖类型时,这是一个缺陷吗
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 模板基类中的静态变量
- C++ 继承:将子类传递给需要基类的函数并获取子类行为
- 带非虚析构函数的基类怎么样?