0

テンプレートを使用せずにスマート ポインターの基本クラスを作成できるかどうか疑問に思っていました。

多くの実装を見てきましたが、すべてテンプレートを使用しています。たとえば、他のクラスの派生元である基本クラスにスマート ポインター ロジックを実装します。

4

4 に答える 4

2

問題は、ポインター メンバーのクラスです。

C# のような言語では、他のすべてのクラスが派生する「オブジェクト」クラスがあるため、可能です。その場合、型の安全性が失われます。

ただし、C++ ではそのようなことはありません。2 つの選択肢があります。

  1. void*reinterpet_castを使用する- 非常に見苦しく、型の安全性のために安全ではありません。
  2. クラスごとに、クラスごとに大量のオーバーロードを記述します。新しいクラスでは機能しないため、実現不可能です。

したがって、最善の方法はテンプレートを使用することです。
ところで、テンプレートのアイデアは非常に優れているため、C# はいくつかのバージョンの後にそれを使用するようになりました。

于 2012-01-08T15:59:37.720 に答える
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 に答える
1

スマート ポインター クラスをリソースの特定のデータ型のみのリソース管理クラスとして機能させたい場合は、テンプレートは必要ありません。

一般的なリソース マネージャー クラスを作成する場合は、テンプレート クラスが必要です。

于 2012-01-08T15:57:59.673 に答える
1

このアプローチの問題点は、メソッドを追加できないことです。はい、必要に応じて継承を使用してスマート ポインターを作成できますが、結果はかなり制限されます。この場合、継承は最善の解決策ではありません。動的ポリモーフィズムが最善の解決策になることはめったにありませんが、これは別の、より大きな議論です (決してそうではないとは言っていないことに注意してください)。

于 2012-01-08T15:59:35.853 に答える