开发者

Linker error when using templates

I'm trying a controlled, learning experiment with my project and it involves creating my own collections and iterators, essentially an array and a linked list. There is something that I'm missing since it compiles with linking errors. I've spent three days examining, coding and recoding this and I really need some help.

I'm using Visual Studio 2010. I'm dabbling in the new C++11 stuff with the new ranged based for, or for each as I think of it. In Visual C++ it is for each (VAR in LIST), but in GCC it is for (VAR : LIST).

Here is the linker errors:

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)

My code is as follows:

template<typename T>
class Iterator
{
public:
    Iterator(T* Start) : Current(Start) { }
    const T& operator*() const { return *Current; }
    const T* operator->() const { return Current; }
    Iterato开发者_JS百科r<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();
}


Looks to be pretty simple, where is your implementation for your begin and end functions in the Collection class?

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

You have to have a specified implementation for each of these, that is what is causing the linker errors.


In the Container class, you should declare begin() and end() as:

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


Whenever a Base class contains non-pure virtual methods, you need to define them somewhere. Otherwise, while creating a Derived class object it will give linker errors such as, undefined reference/symbol. If you don't want to define Container::begin() and Container::end() then declare them as pure virtual.

Here, I have answered a similar question.


for each is Microsoft .NET, eg. managed C++ aka C++/CLI. The real C++11 version is really for(type& var : container).
Next, you got no implementation of your begin and end methods in Container.
Lastly, virtual functions are only in use when using pointers-to-base-types, eg.:

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

Would call the ArrayList<int>::begin() function. Aka, for containers, virtual functions are virtually useless (no pun intended).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜