因此,在最近的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> *

10-05 21:38