模板类问题

时间:2014-08-15 10:27:51

标签: c++ templates

我遇到以下问题。考虑这个(非常简化的)示例。我正在使用我们现有的一个模板类,我可以添加(最多一点)一些通用功能:

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超出范围时,我'忘记'释放{{1}结构,它改为调用'删除'。

解决这个问题的好方法是什么?

  • 我是否创建了从myClass派生的类,我可以编写自己的特定于此问题的析构函数?
  • 我是否可以调整myClass,以便传递某种可选的通用Destructor对象?
  • 我是否可以调整myClass以便(可选)传递要在析构函数中调用的静态函数?
编辑:我可能没有正确解释自己,但是myClass已经被其他地方使用了,所以我不能简单地改变现有的析构函数以适应这个特定的问题

1 个答案:

答案 0 :(得分:4)

立即实施

鉴于可以修改类(保持向后兼容性),您可以扩展类以包括自定义删除器来管理资源(具有合适的默认值)。然后可以为类需要维护的每种类型实现自定义删除。

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());

您还需要通过制作myClass(C ++ 03),删除它们private:来处理您的班级=delete;的副本和作业(C ++ 11)或者适当地实现,即实现完整的拷贝和赋值语义。

您已批评副本和分配已正确实施(这也需要notMine*指针的情况)。如果情况并非如此,那么您可能会遇到更多问题。

C ++ 11还带来了移动语义,可以实现将所有权从myClass的一个实例转移到另一个实例。

更好

std::unique_ptrstd::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());