派生类在C++; 什么是提供C++接口的最优雅的方式,它接受派生类类型,这些类型与它们后面需要检索的不同数据类型成员一起携带。下面的示例说明了这一点,其中容器类提供方法“发布”将是BaseItem的某种派生变体的项。稍后,我想取回派生项并提取其值

派生类在C++; 什么是提供C++接口的最优雅的方式,它接受派生类类型,这些类型与它们后面需要检索的不同数据类型成员一起携带。下面的示例说明了这一点,其中容器类提供方法“发布”将是BaseItem的某种派生变体的项。稍后,我想取回派生项并提取其值,c++,derived,C++,Derived,我希望容器接口(post和receive)在将来保持不变,同时允许定义和“传递”不同的“项”派生类型。模板会更好吗;我宁愿不使用RTTI。也许有一些简单,优雅的答案,但现在我正在努力想它 class ItemBase { // common methods }; class ItemInt : public ItemBase { private: int dat; public: int get() { return dat; } }; class ItemD

我希望容器接口(post和receive)在将来保持不变,同时允许定义和“传递”不同的“项”派生类型。模板会更好吗;我宁愿不使用RTTI。也许有一些简单,优雅的答案,但现在我正在努力想它

class ItemBase {
  // common methods
};

class ItemInt : public ItemBase
{
  private:
    int dat;
  public:
    int get() { return dat; }  
};

class ItemDouble : public ItemBase
{
  private:
    double dat;
  public:
    double get() { return dat; }  
};

class Container {
 public:
   void post(int postHandle, ItemBase *e);      
   ItemBase* receive(int handle); // Returns the associated Item
};

int main()
{
   ItemInt *ii = new IntItem(5);
   Container c;
   c.post(1, ii);

   ItemInt *jj = c.receive(1); 
   int val = jj->get();  // want the value 5 out of the IntItem
}

这绝对是泛型编程的候选者,而不是继承。记住,当您希望对不同的数据类型进行相同的处理时,泛型(模板)是理想的。ItemInt和ItemDouble类违反了OO设计原则(get()方法根据实际的子类型返回不同的数据类型)。通用编程就是为此而构建的。唯一的另一个答案是标记的数据类型,我个人避免使用类似瘟疫的类型。

您的容器类看起来可疑地像一个std::map。在我看来,您的ItemBase类只是“Object”的一个不同名称,即通用基类,我认为它与void*没有太大区别(或比void*更好)。我会避免在单个容器中包含不同类型的项目。如果你的设计似乎需要这样做,我会重新考虑你的设计

怎么样

template<typename T>
class Item
{
  private:
    T dat;
  public:
    T get() { return dat; }  
};

class Container {
 public:
   template<typename T>
   void post(int postHandle, Item<T> *e);      

   template<typename T>
   Item<T>* receive(int handle); // Returns the associated Item
};

int main()
{
   Item<int> *ii = new Item<int>(5);
   Container c;
   c.post(1, ii);

   Item<int> *jj = c.receive<int>(1); 
   int val = jj->get();  // want the value 5 out of the IntItem
}
模板
类项目
{
私人:
T-dat;
公众:
T get(){return dat;}
};
类容器{
公众:
模板
无效邮政编码(内部邮政编码,e项);
模板
Item*receive(int handle);//返回关联的项
};
int main()
{
第二项=新的第(5)项;
容器c;
c、 员额(1,二);
项目*jj=c.接收(1);
int val=jj->get();//希望从初始项中去掉值5
}

纯模板方法不起作用,因为您显然希望容器中有混合类型。您可以使用Boost的
any
之类的工具,尽管我认为您需要恢复实际的代码。在这种情况下,我认为需要一个基类来公开独立于类型的虚拟方法,再加上一个模板化的派生类来保存实际的项:

class Base {
public:
    virtual ~Base() {}
    virtual void post() = 0;
};

template <typename T>
class Item: public Base {
public:
    Item(T const& value): value_(value) {}
    void post() { std::cout << "posting " << this->value_ << "\n"; }
private:
    T value_;
};

返回一个
std::unique_ptr
,以确保分配的对象被释放(如果不使用C++2011,则可以使用
std::auto_ptr
)。此类型可以很容易地转换为其他指针类型,例如转换为更适合放入容器的
std::shared_ptr

尝试Boost.any,其功能非常类似。还请注意,发布的代码存在每个对象的
get
返回类型不同的问题。如果不能使它们成为相同的类型,则必须返回stringstream或其他内容。是的,我同意,但get()函数不是虚拟函数。每个派生类“添加”的是“单独的功能”。还有其他常见的功能使继承成为“必需的”@innocent\u旁观者:在这种情况下,您的main必须将
c.receive()
转换为
IntItem
,然后才能调用
.get()
,因为转换不是隐式的。@Node:是的,receive的调用方知道应该使用什么类型以及如何处理它。我同意我们可以创建一个模板项并让get()返回T。但是post()的第二个参数是什么类型?我想让它接受带有任何模板参数的项目,T.@Innology_bystander:通常我会使
Container::post
Container::recieve
两个模板,并跳过
itemsbase
altogateher。
template <typename T>
std::unique_ptr<Base> make_item(T const& value) {
    return std::unique_ptr<Base>(new Item<T>(value));
}