【问题标题】:Linker error when using templates使用模板时出现链接器错误
【发布时间】:2011-04-14 04:19:41
【问题描述】:

我正在尝试对我的项目进行受控的学习实验,它涉及创建我自己的集合和迭代器,本质上是一个数组和一个链表。我缺少一些东西,因为它编译时带有链接错误。我花了三天时间检查、编码和重新编码,我真的需要一些帮助。

我正在使用 Visual Studio 2010。我正在涉足新的 C++11 东西,我认为新的 ranged based forfor each其中。在 Visual C++ 中是 for each (VAR in LIST),但在 GCC 中是 for (VAR : LIST)

这是链接器错误:

main.obj : error LNK2001: unresolved external symbol "public: virtual class Iterator<int> __thiscall Container<int>::begin(void)const " (?begin@?$Container@H@@UBE?AV?$Iterator@H@@XZ)
main.obj : error LNK2001: unresolved external symbol "public: virtual class Iterator<int> __thiscall Container<int>::end(void)const " (?end@?$Container@H@@UBE?AV?$Iterator@H@@XZ)

我的代码如下:

template<typename T>
class Iterator
{
public:
    Iterator(T* Start) : Current(Start) { }
    const T& operator*() const { return *Current; }
    const T* operator->() const { return Current; }
    Iterator<T>& operator++() { Current++; return *this; }
    bool operator!=(Iterator<T> &Other) { return Current != Other.Current; }

protected:
    T* Current;
};

template<typename T>
class Container
{
public:
    Container() : Count(0) { }
    Container(unsigned int Count) : Count(Count) { }

    unsigned int GetCount() const { return Count; }
    bool IsEmpty() const { return Count == 0; }
    Iterator<T>& GetIterator() const { return begin() };

    // Compatibility with C++0x range-based for requires begin() and end() functions.
    virtual Iterator<T> begin() const;
    virtual Iterator<T> end() const;

protected:
    unsigned int Count;
};

template<typename T>
class ArrayList : public Container<T>
{
public:
    ArrayList() : Items(nullptr), Container(0) { }

    virtual Iterator<T> begin() const
    { 
        return Iterator<T>(Items);
    }

    virtual Iterator<T> end() const
    { 
        return Iterator<T>(Items + Count);
    }

private:
    T *Items;
};

int main()
{
    ArrayList<int> MyList;
    for each (auto Item in MyList)
    { }
    return MyList.GetCount();
}

【问题讨论】:

    标签: c++ visual-studio-2010 templates c++11 linker-errors


    【解决方案1】:

    看起来很简单,你在 Collection 类中的 begin 和 end 函数的实现在哪里?

    virtual Iterator<T> begin() const;
    virtual Iterator<T> end() const;
    

    您必须为其中的每一个指定一个实现,这就是导致链接器错误的原因。

    【讨论】:

    • 即使实现了,也要和声明一起,如果放在.cpp文件里,还是会出现链接错误。由于 Container 似乎是一个抽象容器类,因此将这些方法设为纯虚拟似乎更好。
    • 这两件事都是真的,但他现在显然正在尝试使用该类,并指出需要一个实现应该引导他自己思考这些逻辑和设计决策.
    【解决方案2】:

    在 Container 类中,你应该将 begin() 和 end() 声明为:

    virtual Iterator<T> begin() const = 0;
    virtual Iterator<T> end() const = 0;
    

    【讨论】:

    • 很难想象一个如此单纯的人能支撑我这么久。谢谢你。我的目标是在 Container 上拥有纯虚拟。
    【解决方案3】:

    只要基类包含非纯虚拟方法,您就需要在某处定义它们。否则,在创建派生类对象时,它会给出链接器错误,例如,undefined reference/symbol。 如果您不想定义Container::begin()Container::end(),请将它们声明为pure virtual

    这里,我有answered a similar question

    【讨论】:

      【解决方案4】:

      for each 是 Microsoft .NET,例如。托管 C++ 又名 C++/CLI。真正的C++11版本真的是for(type&amp; var : container).
      接下来,您在 Container 中没有实现 beginend 方法。
      最后,虚函数在使用pointers-to-base-types时使用,例如:

      Container* myCont = new ArrayList<int>();
      auto it = myCont->begin();
      

      将调用ArrayList&lt;int&gt;::begin() 函数。 Aka,对于容器,虚函数实际上是无用的(没有双关语)。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多