簡體   English   中英

如何制作一個可以容納任何類型指針的容器

[英]How do I make a container that holds pointers of any type

這看起來似乎很愚蠢,但是我想創建一個容納任何類型指針的容器,這樣我就可以在其中存儲每個指針,然后在以后輕松刪除它們。 我試過了:

vector<void*> v;

v.push_back(new Dog());
v.push_back(new Cat());

cout <<  v[0]; // prints mem address
cout <<  v[1]; // prints another mem address
cout << *v[0]; // compiler yells at me

但是顯然您不能取消引用void指針。 有沒有一種方法可以使任何類型的指針成為通用容器,而不必使每個類都擴展為稱為“對象”之類的超類?

您可以將指針包裝器實現為從通用基類繼承的模板類,並將其放置到容器中。 大致情況:

class pointer_wrapper_base
{
public:
  virtual void delete_pointee()=0;
protected:
  void *m_ptr;
};

template<class T>
class pointer_wrapper: public pointer_wrapper_base
{
public:
  pointer_wrapper(T *ptr_) {m_ptr=ptr_;}
  virtual void delete_pointee()
  {
    delete (T*)m_ptr;
  }
};

有了此類后,就可以使用例如多變體類,這與變體類相似,但是所有不同的變體都有共同的基類。 如果您想看一下,可以在這里實現: http : //sourceforge.net/p/spinxengine/code/HEAD/tree/sxp_src/core/utils.h (搜索poly_pod_variant):

  std::vector<poly_pod_variant<pointer_wrapper_base> > x;
  x.push_back(pointer_wrapper<Cat>(new(Cat)));
  x[0]->delete_pointee();

或者,如果您可以動態分配包裝器,那么您當然可以只存儲指向vector的pointer_wrap_base指針,例如

std::vector<std::unique_ptr<pointer_wrapper_base> > x;
x.push_back(std::unique_ptr<pointer_wrapper_base>(new(pointer_wrapper<Cat>)(new Cat)));
x[0]->delete_pointee();

考慮使用一些Boost的類,如boost ::任何, http://www.boost.org/doc/libs/1_55_0/doc/html/any.html和他們的示例代碼, HTTP://www.boost .ORG / DOC /庫/ 1_55_0 / DOC / HTML /任何/ s02.html

或者,也查看Boost的變體。

通常,學習Boost。 它會讓您大吃一驚,並加速您的C ++開發。

C ++具有靜態類型系統。 這意味着必須在編譯時知道所有表達式的類型。 解決問題的方法取決於您將如何處理這些對象。

選項1:有CatDog從一個類派生

如果所有對象都有一個公共接口,並且可以使它們派生自類,則這是有道理的。

std::vector<std::unique_ptr<Animal>> vec; // good practice - automatically manage 
                                          // dynamically allocated elements with
                                          // std::unique_ptr

vec.push_back(std::make_unique<Dog>()); // or vec.emplace_back(new Dog());
vec.push_back(std::make_unique<Cat>()); // or vec.emplace_back(new Cat());

std::cout << *v[0];

選項2: boost::any

如果類型不相關,這是有意義的。 例如,您存儲類的int和對象。 顯然,您不能使int從您的類派生。 因此,您可以使用boost::any進行存儲,然后將其強制轉換回對象的類型。 如果轉換為不相關的類型,則會引發類型boost::bad_any_cast的異常。

std::vector<boost::any> vec;
vec.push_back(Dog());
vec.push_back(25);

std::cout << boost::any_cast<int>(vec[1]);

另外,指針。 解決方案“我想正確地管理我的內存”是“不要使用new delete ”,這些工具可以幫助您按特定順序執行此操作:

  • std::string而不是以null終止的字符串
  • std::vector<T>而不是new T[]
  • std::unique_ptr<T>而不是指向多態對象的原始指針
  • ...或std::shared_ptr<T>如果您共享它們)

cout << *((狗*)v [0]);

我在這里假設您的Dog類是可字符串化的,否則您將收到另一種錯誤,但是您的類型轉換問題應通過(Dog *)類型轉換解決。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM