- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我发现我的代码中存在内存泄漏,这是由于仅调用对象的基类析构函数引起的。理解这个问题:我已经将 virtual
添加到接口(interface)类 MyÌnterface
的析构函数中。令我困惑的是,编译器显然为最终调用的辅助类 MyHelper
创建了一个标准析构函数。我用两个不同的编译器试过了。
这让我感到非常惊讶,因为我观察到如果成员或基类引入限制,则不会创建大多数默认实现。 为什么析构函数的保护没有被继承?
#include <iostream>
class MyInterface
{
public:
virtual void doSomethingUseful()=0;
// a lot more functions declared omitted
virtual void doSomethingElse()=0;
virtual void doSomethingIndividual()=0;
protected:
/// protected destructor to forbid calling it on interfaces
~MyInterface() {} // HERE the virtual is clearly missing
};
/// a common base that defaults most functions implementations
class MyHelper: public MyInterface
{
public:
void doSomethingUseful() {}
// a lot more default implementations omitted
void doSomethingElse() {}
};
class SomeImplementation: public MyHelper
{
public:
SomeImplementation()
{
std::cout << "SomeImplementation ctr" << std::endl;
}
~SomeImplementation()
{
std::cout << "SomeImplementation dtr" << std::endl;
}
void doSomethingIndividual()
{
std::cout << "SomeImplementation did it." << std::endl;
}
};
/// user of MyInterface cannot delete object mi passed as parameter
int deleteSafeUsage(MyInterface& mi)
{
mi.doSomethingIndividual();
// would cause a compiler error: delete &mi;
}
/// usage restricted to MyHelper level, only exception is object creation
int testIt()
{
MyHelper* h = new SomeImplementation;
deleteSafeUsage(*h);
delete h; // <- HERE the memory leak happens!
}
这里是上面示例代码的输出,它“显示”了缺少的 SomeImplementation ctr
:
SomeImplementation ctr
SomeImplementation did it.
最佳答案
Constructors and destructors are not inherited .那么为什么他们的知名度会被继承呢?
您可能想要检查标准以确定,但是cppreference这么说,强调我的:
If no user-defined destructor is provided for a class type (struct, class, or union), the compiler will always declare a destructor as an inline public member of its class.
所以,如果你想让~MyHelper
受到保护,你必须显式地声明它。
请注意,如果 MyInterface
有一个虚拟析构函数,则 MyHelper
的隐式析构函数也将是虚拟的。所以这方面是继承的,有点。同样,如果您想确定,您将需要引用标准,但这在 c++ faq lite 中有所提及。
为了完整起见,这里是 Herb Sutters关于如何在一般情况下和析构函数中使用虚拟的指南。
关于c++ - 抽象基类中的析构函数保护在C++中不被继承?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21985200/
我开始考虑在我 future 的项目或重构中实现控制反转容器,我想知道在正确设计依赖项时哪些原则(除了 GoF 模式)可能需要牢记在心。假设我需要构建一个简单的控制台应用程序,如果它可以访问互联网,它
假设我有一个 RxC contingency table 。这意味着有 R 行和 C 列。我想要一个维度为 RC × (R + C − 2) 的矩阵 X,其中包含行的 R − 1 “主效应”以及列的
我正在尝试使用 DKMS 为正在运行的内核 (4.4) 构 build 备树覆盖。我天真的 Makefile 如下: PWD := $(shell pwd) dtbo-y += my-awsome-o
我有一个 sencha touch 项目。我是用 phonegap 2.9 构建的,并且可以正常工作 device.uuid 返回到设备 ID。当我尝试使用 3.1 device.uuid 构建时抛出
我在安装了 Xcode 4.5.1 的 Mt Lion 上运行。 默认情况下,当我构建并部署到 iOS 5.1 设备时,显示会在我旋转设备时旋转,但当我部署到 iOS 6 模拟器或运行 iOS 的 i
我正在尝试使用 Google Analytics Reporting API v4 构建多折线图。 一张图表,其中我按每天的 session 计数为每个设备(台式机/平板电脑/移动设备)设置了一条线。
我一生都无法使用 xcode 组织者“自动设备配置”中的“团队配置配置文件”在 xcode 4.0.1 中将我的应用程序构建到我的 iPad 上。 该应用程序完美地构建到模拟器,但当我构建到 iPad
我是一名优秀的程序员,十分优秀!