C ++链接错误:使用模板化类的未定义符号 [英] C++ Linking Errors: Undefined symbols using a templated class

查看:237
本文介绍了C ++链接错误:使用模板化类的未定义符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写的一个类中出现了一些非常奇怪的链接错误.我完全找不到能描述正在发生的事情的东西.

I'm getting some really wierd linking errors from a class I wrote. I am completely unable to find anything that will describe what is happening.

Visual Studio(Windows XP)

Visual Studio (Windows XP)

players.obj:错误LNK2019:未解析的外部符号公共:__ thiscall TreeNode :: TreeNode(void)"(?? 0?$ TreeNode @ VPlayer @@@@@@ AE @ XAE)在函数公共:__ thiscall PlayerList中引用" :: PlayerList(void)"(?? 0PlayerList @@ QAE @ XZ)

players.obj : error LNK2019: unresolved external symbol "public: __thiscall TreeNode::TreeNode(void)" (??0?$TreeNode@VPlayer@@@@QAE@XZ) referenced in function "public: __thiscall PlayerList::PlayerList(void)" (??0PlayerList@@QAE@XZ)

Xcode(OSX 10.5)

Xcode (OSX 10.5)

未定义的符号:"TreeNode ::〜TreeNode()",引用自players.o中的PlayerList ::〜PlayerList().

Undefined symbols: "TreeNode::~TreeNode()", referenced from: PlayerList::~PlayerList()in players.o

头文件:generics.h

Header File: generics.h

class TreeNode : public BaseNode{
public:
    const static int MAX_SIZE = -1; //-1 means any size allowed. 
    const static int MIN_SIZE = 0;
    //getters
    int size() const;
    vector<C*> getChildren() const;
    //setters
    void setChildren(vector<C*> &list);
    //Serialization
    virtual void display(ostream &out) const;
    virtual void read(istream &in);
    virtual void write(ostream &out) const;
    //Overrides so SC acts like an array of sorts. 
    virtual C* get(int id) const; 
    virtual int get(C *child) const;
    virtual bool has(C *child) const;
    virtual C* pop(int id);
    virtual void push(C *child);
    virtual TreeNode& operator<< (C *child); //append
    virtual void remove(int id); //Clears memory 
    virtual void remove(C *child); //Clears memory 
    //Initalizers
    TreeNode();
    TreeNode(istream &in);
    TreeNode(long id, istream &in);
    TreeNode(BaseNode* parent, istream &in);
    TreeNode(long id, BaseNode* parent);
    TreeNode(long id, BaseNode* parent, istream &in);
    ~TreeNode();
    string __name__() const{ return "TreeNode"; }
protected:
    void clearChildren();
    void initalizeChildren();
    vector<C*> _children;
};

TreeNode子类中的代码

Code from a subclass of TreeNode

PlayerList::PlayerList() : TreeNode<Player>(){}
PlayerList::PlayerList(istream &in) : TreeNode<Player>(in){}
PlayerList::~PlayerList(){}

推荐答案

在.cpp文件中定义模板时,必须使用所有类型/模板参数显式实例化该模板,已知模板将像这样预先使用(将其放入.cpp文件):

When you define your template in a .cpp file, you have to explicitly instantiate it with all the types / template parameters known the template will be used beforehand like this (put it in the .cpp file):

template class TreeNode<Player>;

如果您不知道将使用哪个模板参数来使用模板,则必须将所有定义都放在标题中.喜欢

If you don't know with which template parameters the template will be used, you have to put all the definitions into the header. like

template<typename T>
class TreeNode {
public:
   TreeNode() /* now, also put the code into here: */ { doSomething(); }
};

原因是,当您要从某个地方使用模板时,编译器必须能够为该模板的特定实例生成代码.但是,如果将代码放入.cpp文件并进行编译,则编译器将无法使用代码来生成实例化(除非使用臭名昭著的export关键字,该关键字仅受几个编译器.)

The reason is that when you are going to use the template from somewhere, the compiler has to be able to generate the code for that specific instantiation of the template. But if you place the code into a .cpp file and compile it, there is no way for the compiler to get its hands on the code to generate the instantiation (except when using the infamous export keyword, which is only supported by very few compilers).

这也是我的C ++陷阱答案中的一项:应该使用什么C ++陷阱我避免吗?

This is also an entry in my C++ Pitfalls answer: What C++ pitfalls should I avoid?

这篇关于C ++链接错误:使用模板化类的未定义符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆