C++继承测试
C++ Inheritance quiz
最近有人问我一个基本的C++问题,我实际上不知道答案,也从来没有找到答案。问题是:
运行此程序时,可能会导致错误。你会对基类做什么更改来修复它?
#include <iostream>
class Base {
public:
virtual void ShowMessage () {
std::cout << "Base class messagen";
}
// Something should be added here!
};
class Derived : public Base {
public:
explicit Derived (const std::string & value)
: myValue(value)
{
}
virtual void ShowMessage () {
std::cout << "Derived class message " << myValue << "n";
}
private:
std::string myValue;
};
int main () {
Base * obj = new Derived("Test message");
obj->ShowMessage();
delete obj;
}
它在我的机器上编译和运行都很好。有人知道他们在找什么吗?
您需要向基类添加一个虚拟析构函数。
class Base {
public:
virtual void ShowMessage () {
std::cout << "Base class messagen";
}
virtual ~Base() {}
};
在您的情况下,Derived::myvalue将不会正确释放。
delete obj;
它不会知道有一个CCD_ 1要销毁/解除分配,除非该销毁器是以多态方式调用的(即通过虚拟调度)。这是因为在没有虚拟调度的情况下,基类析构函数会运行,而且它不需要担心std::string
数据成员,因此不包括与之相关的代码
指导原则很简单:无论何时使用指向基类的指针删除对象,都应该确保基类具有虚拟析构函数。
其他任何事情都存在上述问题,并且在技术上都是未定义的行为。虽然尝试对未定义的行为进行"推理"不是一个好主意,因为你不能确定发生的事情不会比预期的更糟(如果不是现在,那么在一些更高级的编译器/编译器版本上,或者使用不同的编译开关或周围的代码,另一个CPU等),在这种情况下,内存泄漏是一个明显的可能结果:std::string构造函数可以被期望动态地new
生成一个字符数组,如果运行的话,指导程序会删除它。尽管如此,也可能存在其他问题——如果派生类的数据成员是共享指针,那么指向的对象可能无法正确地进行销毁/释放,如果存在文件句柄、共享内存句柄、线程、锁等,则无法调用销毁器的后果可能会很严重:数据可能无法被清除到预期目的地,应用程序可能会在多次泄漏后耗尽资源,或者稍后当其他代码试图获取它仍然持有的锁时,它可能会挂起。。。。
您必须使析构函数为虚拟的,因为删除没有虚拟析构函数的多态类型会导致未定义的行为:
根据5.3.5.3:
在第一个备选方案(删除对象)中,如果要删除的对象与其动态类型、静态类型不同type应为待处理对象的动态类型的基类已删除且静态类型应具有虚拟析构函数或行为未定义。在第二个备选方案(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,行为是未定义的。
- 继承函数的重载解析
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- 继承期间显示未知行为的子类
- 头文件-继承c++
- 尽管测试成功,CppUnit测试核心仍被丢弃.为什么
- 为什么在保护模式下继承升级不起作用
- 数据成员SFINAE的C++17测试:gcc vs clang
- 通过继承类使用来自不同命名空间的运算符
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 混合组合和继承的C++问题
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 为什么二进制搜索在我的测试中不起作用
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 从父数组测试用例构造二叉树失败
- Boost单元测试夹具继承测试类,是否可以访问受保护的方法
- 为什么私有继承不能解决静态函数的歧义?(在 MSVC 中测试)
- 继承的模板类成员在链构造函数中测试良好,但此后"lost"
- C++继承测试
- 使用模板和继承设计测试