2011-04-14 62 views
1

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

我使用Visual Studio 2010中,我在涉足新的C++ 11的东西与新基于不等的,或每个因为我想起来了。在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 " ([email protected][email protected]@@[email protected]@@XZ) 
main.obj : error LNK2001: unresolved external symbol "public: virtual class Iterator<int> __thiscall Container<int>::end(void)const " ([email protected][email protected]@@[email protected]@@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(); 
} 

回答

1

在容器类,你应该申报开始()和end()为:

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

很难想象这么简单的人可以让我坚持这么久。谢谢。我的目标是在Container上获得纯虚拟。 – 2011-04-14 13:32:36

1

for each是微软.NET,例如。托管C++又名C++/CLI。真正的C++ 11版本真的是for(type& var : container)
接下来,您在Container中没有实施您的beginend方法。
最后,使用指针到基本类型,例如:

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

能打电话通知ArrayList<int>::begin()功能时虚函数只有使用。也就是说,对于容器来说,虚拟功能实际上是无用的(不是双关语)。

+0

Visual C++'for each,in'具有基于C++ 0x范围的所有功能,只是语法不同。看到这篇文章:http://msdn.microsoft.com/en-us/library/ms177202(v=VS.100).aspx – 2011-04-14 13:49:28

4

看起来很简单,你在Collection类中的开始和结束函数的实现在哪里?

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

您必须为每个指定的实现,这是什么导致链接器错误。

+0

即使它被实现,它应该与声明一起,如果你把它放在一个.cpp文件,你仍然会得到链接错误。由于Container似乎是一个抽象的容器类,所以将这些方法变为纯虚拟似乎更好。 – fbafelipe 2011-04-14 04:44:00

+0

这两件事情都是真实的,但他显然正试图利用现在的班级,并指出需要有一个实施应该引导他自己思考那些逻辑和设计决定。 – radman 2011-04-14 04:49:21

1

每当一个基类包含非纯虚方法,你需要的地方定义它们。否则,在创建派生类对象时,它会给出链接器错误,例如,未定义的引用/符号。 如果您不想定义Container::begin()Container::end(),则将它们声明为pure virtual。我有answered a similar question