我遇到了以下问题。考虑这个(非常简化的)例子。我正在使用我们现有的模板类之一,我可以添加(在一定程度上)一些通用功能:
template<typename T> class myClass
{
public:
typedef T element_type;
explicit myClass(T* p = 0) : ptr(p) {}
~myClass() { delete ptr; };
......
private:
T* ptr;
};
我还使用了一个外部库(我显然无法调整),其中定义(比方说)struct notMine
。由于这是一个 C 风格的库,一个人做了某种 notMine* nmPtr = createNotMine();
调用,我需要记住 freeNotMine(nmPtr);
当我完成。
现在我想将 myClass
与指向 notMine
结构的指针一起使用,但问题是当 myClass
超出范围时,我“忘记”释放此 notMine
结构,它改为调用“delete”。
解决这个问题的好方法是什么?
- 我是否创建派生自 myClass 的类,我可以在其中编写我自己的特定于此问题的析构函数?
- 我是否调整 myClass 以便传递某种可选的通用 Destructor 对象?
- 我是否调整 myClass 以便我可以(可选地)传递要在析构函数中调用的静态函数?
编辑:我可能没有正确解释自己,但是 myClass 已经在其他地方使用了,所以我不能简单地更改现有的析构函数来适应这个特定问题
最佳答案
为您立即实现
鉴于该类可以修改(保持向后兼容性),您可以扩展该类以包含自定义删除器来管理资源(具有合适的默认值)。然后可以为类需要维护的每种类型实现自定义删除器。
template <typename T>
struct DefaultDeleter {
void operator()(T* ptr) const {
delete ptr;
}
}
struct NotMineDeleter { // or a specialisation of DefaultDeleter
void operator()(notMine* nmPtr) const {
if (nmPtr)
freeNotMine(nmPtr);
}
}
template<typename T, typename Deleter = DefaultDeleter<T> >
class myClass
{
public:
typedef T element_type;
explicit myClass(T* p = 0) : ptr(p) {}
~myClass() { deleter_(ptr); };
......
private:
Deleter deleter_;
T* ptr;
};
myClass
现在可以按如下方式用于外部库;
myClass<notMine, NotMineDeleter> obj(createNotMine());
您还需要通过将它们设为 private:
(C++03) 或将它们删除 来处理类
(C++11) 或适本地实现,即实现完整的复制和赋值语义。myClass
的拷贝和分配=delete;
您评论说复制和赋值实现得当(notMine*
指针也需要如此)。如果不是这种情况,那么您可能会遇到更多问题。
C++11 还带来了移动语义,可以实现将所有权从 myClass
的一个实例转移到另一个实例。
更好
将 std::unique_ptr
或 std::share_ptr
与调用 freeNotMine(nmPtr)
的自定义删除器一起使用。
RAII - 看起来你正在做的是实现一个经典的 RAII 类。这是一件非常好的事情,也是 C++ 中资源类的核心惯用用法之一。
上述双重删除器的替代方法
使用模板特化,可以简化实现(但本质上仍然为要维护的每种类型维护删除器)如下;
template <typename T>
struct Deleter {
void operator()(T* ptr) const {
delete ptr;
}
}
template <>
struct Deleter<notMine> {
void operator()(notMine* nmPtr) const {
if (nmPtr)
freeNotMine(nmPtr);
}
}
template<typename T>
class myClass
{
public:
typedef T element_type;
explicit myClass(T* p = 0) : ptr(p) {}
~myClass() { deleter_(ptr); };
......
private:
Deleter<T> deleter_;
T* ptr;
};
myClass
现在可以按如下方式用于外部库;
myClass<notMine> obj(createNotMine());
关于c++ - 模板类问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25324907/