带有模板的 c++ 析构函数:T 可以是指针,也可以不是指针

c++ Destructor with templates: T could be a pointer or not

本文关键字:指针 也可以 析构函数 c++      更新时间:2023-10-16

我在编写模板类时遇到了一个小问题 win C++.问题相当简单:我不知道是否要对参数化类型进行delete,因为它可以,或者不能,是一个指针。

我已经看到这个:模板类c中的析构函数:如何删除可能是指针或不是指针的字段?

我已经实现了第一个解决方案,但这需要我专注于整个班级,所以这意味着我必须有 2 个类:

template<class T>
class Node {
private:
    T _content;
public:
    Node(const T c); 
    ~Node();
};

template<class T>
class Node<T*> {
private:
    T _content;
public:
    Node(const T c); 
    ~Node();
};

我只想拥有第二个版本,并且只专门介绍析构函数,如下所示:

template<class T>
class Node<T*> {
private:
    T _content;
public:
    Node(const T c); 
    ~Node();
};
template <class T>
Node<T>::~Node() {
    while(!_adjacent.isEmpty()) {
        disconnectFrom(_adjacent.first());
    }
}
template <class T>
Node<T*>::~Node() {
    while(!_adjacent.isEmpty()) {
        disconnectFrom(_adjacent.first());
    }
    delete _content;
}

但随后我收到以下错误:

Node.hpp:43:17: error: invalid use of incomplete type ‘class Node<T*>’
Node.hpp:8:7: error: declaration of ‘class Node<T*>’

有没有办法只专门化构造函数以避免有 2 个类(我的 Node 类比我在这里显示的要大得多)?

谢谢!

一个解决方案是使用特征类:

template<typename T> struct delete_traits
{
  void destroy(T&) {}
};
template<typename T> struct delete_traits<T*>
{
  void destroy(T* p) { delete p; }
};

然后在你的类析构函数中写入

delete_traits<T>::destroy(_contents);

除了不必专门化Node模板之外,它还具有额外的优势,即您只需添加另一个模板专用化,即可轻松添加其他方法来销毁内容,而无需触及您定义Node的文件:

// assumes that mylib_handle is a truly different type, maybe a C struct
// from the C interface of a library
template<> struct delete_traits<mylib_handle>
{
  void destroy(mylib_handle& h) { mylib_handle_free(m); }
};

根本不专门研究 Node。只需为您的意图使用正确的类型:

  • 唯一所有权:std::unique_pointer<T>
  • 共享所有权:std::shared_pointer<T>
    • 共享所有权的反向链接:std::weak_pointer<T> .
  • 无所有权:原始指针

如果需要特定的析构函数,这些模板具有该参数。
此外,您可以将它们用于句柄等,即使它们没有命名为指针。

似乎你想要这个:

template<class T>
class Node {
private:
    T _content;
public:
    Node(const T c) : _content { c } {}
    ~Node() {}
};
template<class T>
class Node<T*> {
private:
    T* _content;
public:
    Node(const T* c) : _content { c } {}
    ~Node() { delete _content; }
};

而且,正如@Constructor所说,不,你不能只专注于析构函数,你必须做整个班级......但是,如果类更大,则可以将通用性重构为基类,这样就可以得到如下内容:

template<class T>
class BaseNode {
private:
  template<class> friend class Node;
    T _content;
public:
    BaseNode(T c) : _content { c } {}
    ~BaseNode() {}
};
template<class T>
struct Node : BaseNode<T> {
  Node(T c) : BaseNode<T>(c) {};
  ~Node() {}
};
template<class T>
struct Node<T*> : BaseNode<T*> {
  Node(T* c) : BaseNode<T*>(c) {};
  ~Node() { delete BaseNode<T*>::_content; }
};
相关文章: