0

我想知道是否可以在不使用模板的情况下创建智能指针基类?

我见过许多实现,但都使用模板。例如,在其他类派生的基类中实现智能指针逻辑。

4

4 回答 4

2

问题是您的指针成员的类。

在像 C# 这样的语言中,这是可能的,因为有一个“对象”类,所有其他类都派生自该类。在这种情况下,您将失去类型安全性。

然而,在 C++ 中你没有这样的东西,这让你有 2 个选择:

  1. 使用void*reinterpet_cast - 非常难看,由于类型安全,真的不安全。
  2. 为你的班级写大量的重载——每个班级。不可行,因为它不适用于新课程。

因此,最好的方法是使用模板。
顺便说一句,模板的想法太好了,以至于 C# 在某个版本之后开始使用它。

于 2012-01-08T15:59:37.720 回答
1

如果您希望您的智能指针类仅充当特定数据类型资源的资源管理类,那么您不需要模板。

如果您打算编写一个通用资源管理器类,那么您确实需要一个模板类。

于 2012-01-08T15:57:59.673 回答
1

使用这种方法的问题是您无法添加方法。是的,如果需要,您可以使用继承来创建智能指针,但结果会相当有限。在这种情况下,继承并不是最好的解决方案。动态多态性很少是最好的解决方案,但这是一个不同且更大的讨论(请注意,我没有说过它永远不会)。

于 2012-01-08T15:59:35.853 回答
1

我不知道为什么

#include <iostream>

class void_scoped_ptr {
public:
  virtual ~void_scoped_ptr() = 0;
  void operator=(void_scoped_ptr const&) = delete;

  explicit operator bool() const { return ptr != 0; }

protected:
  void_scoped_ptr(void* p) : ptr(p) {};

  void* ptr;
};

void_scoped_ptr::~void_scoped_ptr() {}

#define MAKE_DERIVED_SCOPED_BASE(T, NAME, DELETE, DEREF)                    \
class NAME : void_scoped_ptr {                                              \
public:                                                                     \
  typedef T element_type;                                                   \
  typedef element_type* ptr_type;                                           \
  typedef element_type const* const_ptr_type;                               \
                                                                            \
  NAME(ptr_type p) : void_scoped_ptr(p) {}                                  \
  ~ NAME() { DELETE cast(); }                                               \
  void reset(ptr_type p) {                                                  \
    DELETE cast();                                                          \
    ptr = p;                                                                \
  }                                                                         \
                                                                            \
  DEREF                                                                     \
  element_type& operator*() { return *cast(); }                             \
  element_type const& operator*() const { return *cast(); }                 \
                                                                            \
protected:                                                                  \
  ptr_type cast() { return static_cast<ptr_type>(ptr); }                    \
  const_ptr_type cast() const { return static_cast<ptr_type>(ptr); }        \
}

#define MAKE_DERIVED_SCOPED_PTR(T)                                          \
  MAKE_DERIVED_SCOPED_BASE(T, T ## _scoped_ptr, delete,                     \
    ptr_type operator->() { return cast(); }                                \
    const_ptr_type operator->() const { return cast(); }                    \
  )
#define MAKE_DERIVED_SCOPED_ARRAY(T)                                        \
  MAKE_DERIVED_SCOPED_BASE(T, T ## _scoped_array, delete [],                \
    element_type& operator[](size_t i) { return cast()[i]; }                \
    element_type const& operator[](size_t i) const { return cast()[i]; }    \
  )

struct TestClass {
  TestClass() { std::cout << "construct\n"; }
  ~TestClass() { std::cout << "destruct\n"; }

  void f() { std::cout << "f()\n"; }
};

typedef MAKE_DERIVED_SCOPED_PTR(TestClass) test_ptr;
typedef MAKE_DERIVED_SCOPED_ARRAY(TestClass) test_array;

int main() {
  {
    test_ptr p(new TestClass);
    p->f();
  }

  {
    test_array a(new TestClass[3]);
    a[2].f();
  }
}
于 2012-01-08T17:12:20.050 回答