因此,在最近的一个 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;
};
注册表变量在实现文件的顶部正确初始化,并在其构造函数中添加到特定数据包类型(在本例中为 Packet0Connect)及其 ID 的映射。我非常喜欢我设法做到这一点的方式,因为它不会在堆栈上分配任何内存。上面在 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++ 一起工作。我知道我可以在定义类之后将寄存器设为全局变量,但如果我可以让它作为静态成员变量工作,我不希望这样做。