在这种情况下应该使用C ++模板吗?

时间:2009-03-25 00:09:52

标签: c++ templates

我有一个客户端用来Get()数据包的类。该数据包包含一个std :: vector,其类型在我的Interface类内部生成数据包之前是未知的(在本例中,它取决于Packet :: type变量)。

我想知道模板是否可以用于此,因为Packet类只是一个泛型类,其类型可以是几乎任何东西。

据我所知,它的问题是客户端不知道它是什么类型的数据包,直到他获得数据包并查看Packet :: type成员。所以,这不会起作用,因为他无法声明Get()将返回的变量(?)

在这种情况下可以优雅地使用模板吗?

我能想到的另一种选择是定义一个基类,并为每种类型创建一个子类。然后,Get()方法可以返回指向基类的指针。然后,客户端可以简单地查看Packet :: type(packet->类型)并将其转换为适当的子类。但那有点乱?有更优雅的解决方案吗?

下面的代码粗略地演示了这个场景:

enum
{
  T_FLOAT,
  T_COMPLEX
} TYPE_ENUM;

// T can either be of type float or std::complex
template<typename T>
class Packet
{
public:
  TYPE_ENUM       type;
  std::vector<T>  data;
};

class Interface
{

public:
  // Method that client calls to obtain the packet
  Packet<>  Get()
  {
    return queue.pop(); // return current packet in queue
  }

private:
  Queue<Packet>   queue;
};

3 个答案:

答案 0 :(得分:8)

模板都是关于编译时类型解析...如果在运行之前无法确定类型,那么您就不适合应用模板。

您需要按照您的描述对最终数据包类型进行运行时切换。

答案 1 :(得分:5)

使用抽象基类和虚方法对数据包类型进行操作。您不应该转换数据包类。模板类的集合是有问题的 - 您将无法添加和删除项目。

答案 2 :(得分:3)

您可能希望创建一个基类,并保留您拥有的模板Packet类。调用此基类PacketBase。您的Packet类将派生自新的PacketBase类。也就是说每个分组&lt;&gt;在编译时生成的类型将派生自PacketBase。

class PacketBase
{ 
};

// T can either be of type float or std::complex or ...
template<typename T>
class Packet : public PacketBase
{
public:
  std::vector<T>  data;

  //Put other members you need here
  //Note you don't need the type member that you had before. 
};

Interface :: Get将返回PacketBase *。这里PacketBase仅用作保存任何Packet&lt;&gt;的通用名称。类型。该队列将存储PacketBase *的集合。

class Interface
{

public:
  // Method that client calls to obtain the packet
  PacketBase*  Get()
  {
    return queue.pop(); // return current packet in queue
  }

private:
  Queue<PacketBase*>   queue;
};

要确定您拥有哪种类型的数据包,可以将RTTI与dynamic_cast结合使用。

InterfaceObject o;
//fill the queue
PacketBase *pPacket = o.Get();
if(dynamic_cast<Packet<float> * >(pPacket) != NULL)
   ;//You have a Packet<float>
else if(dynamic_cast<Packet<std::complex> * >(pPacket) != NULL)
   ;//You have a Packet<std::complex>
//... for each Packet<> type you have

您还可以使用一些虚拟方法来增强PacketBase。然后你可以直接调用它们而不是RTTI dynamic_cast。