6

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

我想要的主要是容器接口(发布和接收)在未来保持不变,同时允许定义不同的“项目”派生类型并通过它“传递”。不知何故,模板会更好吗?我宁愿不使用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
}
4

4 回答 4

5

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

于 2012-01-04T21:52:02.207 回答
1

怎么样?

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
}
于 2012-01-04T22:20:37.357 回答
0

纯模板方法不起作用,因为您显然希望在容器中具有混合类型。any尽管我认为您需要恢复实际值,但您可以使用类似 Boost 的东西。在这种情况下,我认为需要一个基类来公开类型无关和虚拟方法以及一个模板化的派生类来保存实际项目:

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_;
};

这种方法避免了Item为另一种值类型编写任何派生类的需要。为了使创建这些野兽更容易,您可能还想创建一个合适的创建函数,例如

template <typename T>
std::unique_ptr<Base> make_item(T const& value) {
    return std::unique_ptr<Base>(new Item<T>(value));
}

返回Astd::unique_ptr<Base>以确保释放分配的对象(如果您不使用 C++2011,则可以使用std::auto_ptr<T>)。这种类型可以很容易地转换为其他指针类型,例如std::shared_ptr<Base>更适合放入容器中的指针类型。

于 2012-01-04T23:48:03.103 回答
0

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

于 2012-01-04T22:17:25.493 回答