因此,在最近的C ++项目中,我实现了一个类似于包工厂的系统,其中每个新的包类都使用静态寄存器自动进行自身注册。数据包类型之一如下:
class Packet0Connect : public Packet{
public:
Packet0Connect();
Packet0Connect(const std::string& name, const std::string& info);
virtual void write(std::ostream& os) const;
virtual void read(std::istream& is);
virtual Packet* clone() const;
std::string name, info;
private:
static const PacketRegister<Packet0Connect> registry;
};
这是PacketRegister的样子:
template<class P>
class PacketRegister{
public:
PacketRegister(){
PacketMap* packetMap = PacketManager::getPacketMap();
if(packetMap->count(prototype.packetID) == 0){
packetMap->insert(std::make_pair(prototype.packetID, (const Packet*)&prototype));
}
}
P prototype;
};
注册表变量已在实现文件的顶部正确初始化,并在其构造函数中使用其ID向特定的数据包类型(在本例中为Packet0Connect)添加了映射。我很喜欢这样做,因为它不会在堆栈上分配任何内存。上面在Mac OSX上使用GCC 4.2.1可以很好地进行编译,但是,当我尝试在32位Windows Vista上使用Visual C ++ 2010进行编译时,遇到了此错误:
error C2079: 'PacketRegister<P>::prototype' uses undefined class 'Packet0Connect'
with
[
P=Packet0Connect
]
see reference to class template initialization 'PacketRegister<P>' being compiled
with
[
P=Packet0Connect
]
在对错误进行了一些搜索之后,我发现当您尝试使用正向声明的类作为模板参数时,通常会抛出该错误。这确实是有道理的,因为在PacketRegister时没有完全定义Packet0Connect,但是必须有一种方法可以使它与VC ++一起使用。我知道我可以在定义类后使寄存器成为全局变量,但是我不希望它可以作为静态成员变量来工作。
最佳答案
这是因为编译器无法确定Packet0Connect
的大小。将Packet0Connect::registry
的类型从PacketRegister<Packet0Connect>
更改为PacketRegister<Packet0Connect> *
。