我有一个类,我的客户使用它来获取()一个包。该数据包包含一个std::vector,其类型直到在我的Interface类中内部生成数据包时才知道(在本例中,它取决于Packet::type变量)。
我想知道是否可以使用模板,因为Packet类只是一个泛型类,它的类型几乎可以是任何类型。
据我所知,它的问题在于,客户端在获得数据包并查看Packet::type成员之前,不知道它是什么类型的数据包。因此,这将不起作用,因为他不能声明Get()将返回(?)的变量。
在这种情况下,模板能被优雅地使用吗?
我能想到的一个替代方案是定义一个基类,并为每种类型创建一个子类。然后,Get()方法可以返回一个指向基类的指针。然后,客户端可以简单地查看Packet::type (packet->type)并将其转换为适当的子类。但这有点乱吗?有没有更优雅的解决方案?
下面的代码大致演示了这个场景:
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;
};发布于 2009-03-25 00:15:10
您可能希望创建一个基类,并保留已有的模板包类。将此基类称为PacketBase。您的数据包类将派生自新的PacketBase类。也就是说,在编译时生成的每个Packet<>类型都将从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<>类型的泛型名称。队列将存储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;
};要弄清楚您拥有的是哪种类型的数据包,可以在dynamic_cast中使用RTTI。
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的东西。
发布于 2009-03-25 00:16:08
模板都是关于编译时的类型解析...如果直到运行时才能确定类型,那么就不适合应用模板。
您需要让运行时切换到您所描述的最终数据包类型。
发布于 2009-03-25 00:17:00
对数据包类型的操作使用抽象基类和虚拟方法。您不应该需要强制转换packet类。一个模板化的类集合是有问题的--你在其中添加和删除项目时会遇到麻烦。
https://stackoverflow.com/questions/679759
复制相似问题