【问题标题】:C++ Undefined reference to custom maps iterator functionsC++ 对自定义映射迭代器函数的未定义引用
【发布时间】:2012-05-31 01:51:57
【问题描述】:

我已经为分配创建了一个自定义映射(它是一个通用模板化映射,具有它自己的自定义迭代器和部分专业化),但是当应用程序尝试在它的代码中使用它时,我得到了对它所有函数的未定义引用.

我在这里查看了其他类似情况的问题,我猜我的命名空间或迭代器的位置有错误,或者导致应用程序找不到它?

以下是相关代码:

        #ifndef MAP_H
#define MAP_H

#define SIZE 101

#include <string>

using std::string;

namespace myMap{


    ////////////////////START TEMPLATE//////////////////////

    template<class K, class V>
    class map
    {
        private:
            typedef struct SNode{
                K first;
                V second;
                SNode* next;
            } Node;

            Node** hashArray;
            Node* head;
            Node* tail;
            Node* lastEntry;

        public:
            map();
            ~map();

            V generateHash(K first);
            void addPair(K first, V second);
            void checkHeadTail();
            int count(K key);

            V& operator[](K first);

            class iterator
            {
                private:
                    Node* currentNode;
                    K first;
                    V second;
                public:
                    iterator();
                    iterator(Node* pos);
                    ~iterator();

                    void operator++(int);
                    Node* operator->();
                    bool operator!=(iterator other);
            };

            iterator begin(){iterator iter(head); return iter;}
            iterator end(){iterator iter(NULL); return iter;}
    };

    template<class K, class V>
    map<K, V>::map()
    {
        hashArray = new Node*[SIZE];
        for(unsigned int i = 0; i < SIZE; i++){
            hashArray[i] = NULL;
        }

        head = NULL;
        tail = NULL;
        lastEntry = NULL;
    }

    template<class K, class V>
    map<K, V>::~map()
    {
        for(unsigned int i = 0; i < SIZE; i++){
            if(hashArray[i] != NULL){
                Node* tmpNode = hashArray[i];
                Node* currentNode = hashArray[i];
                while(currentNode){
                    currentNode = currentNode->next;
                    delete tmpNode;
                    tmpNode = currentNode;
                }
            }
        }

        delete [] hashArray;
    }

    template<class K, class V>
    V map<K, V>::generateHash(K first)
    {
        V hash = 0;
        for(unsigned int j = 0; j < first.length(); j++){
            hash += first[j];
        }
        return hash % SIZE;
    }

    template<class K, class V>
    void map<K, V>::checkHeadTail()
    {
        if(hashArray[0] != NULL){
            head = hashArray[0];
            tail = hashArray[0];
        }

        Node* currentNode = *hashArray;
        while(currentNode->next){
            currentNode = currentNode->next;
        }
        tail = currentNode;
    }

    template<class K, class V>
    void map<K, V>::addPair(K first, V second)
    {
        Node* newEntry = new Node;
        newEntry->first = first;
        newEntry->second = second;
        newEntry->next = NULL;

        V hash = generateHash(first);

        if(hashArray[hash] == NULL){
            hashArray[hash] = newEntry;
            lastEntry = newEntry;
        } else {
            Node* currentNode = hashArray[hash];
            while(currentNode->next){
                if(currentNode->first == first){
                    currentNode->second += second;
                    lastEntry = currentNode;
                    return;
                }
                currentNode = currentNode->next;
            }
            if(currentNode->first == first){
                currentNode->second += second;
                lastEntry = currentNode;
                return;
            } else {
                currentNode->next = newEntry;
                lastEntry = newEntry;
                return;
            }
        }
        checkHeadTail();
    }

    template<class K, class V>
    V& map<K, V>::operator[](K first)
    {
        V second = 0;
        addPair(first, second);

        return lastEntry->second;
        checkHeadTail();
    }

    template<class K, class V>
    int map<K, V>::count(K key)
    {
        V hash = generateHash(key);
        if(hashArray[hash] != NULL){
            return true;
        }
        return false;
    }

    template<class K, class V>
    void map<K, V>::iterator::operator++(int)
    {
        currentNode = currentNode->next;
    }

    template<class K, class V>
    bool map<K, V>::iterator::operator!=(map::iterator other)
    {
        if(first == other->first) return false; return true;
    }

    template<class K, class V>
    typename map<K, V>::Node* map<K, V>::iterator::operator->()
    {
        return currentNode;
    }

    template<class K, class V>
    map<K, V>::iterator::iterator()
    {
        currentNode = NULL;
    }

    template<class K, class V>
    map<K, V>::iterator::iterator(Node* pos)
    {
        currentNode = pos;
    }

    ////////////////////SPECIALISATION///////////////////////////////

    template<class V>
    class map<string, V>
    {
        private:
            typedef struct SNode{
                string first;
                V second;
                SNode* next;
            } Node;

            Node** hashArray;
            Node* head;
            Node* tail;
            Node* lastEntry;

        public:
            map();
            ~map();

            V generateHash(string first);
            void addPair(string first, V second);
            void checkHeadTail();
            V count(string key);

            V& operator[](string first);

            class iterator
            {
                private:
                    Node* currentNode;
                    string first;
                    V second;
                public:
                    iterator();
                    iterator(Node* pos);
                    ~iterator();

                    void operator++(V);
                    Node* operator->();
                    bool operator!=(iterator other);
            };

            iterator begin();
            iterator end();
    };

    template<class V>
    map<string, V>::map()
    {
        hashArray = new Node*[SIZE];
        for(unsigned int i = 0; i < SIZE; i++){
            hashArray[i] = NULL;
        }

        head = NULL;
        tail = NULL;
        lastEntry = NULL;
    }

    template<class V>
    map<string, V>::~map()
    {
        for(unsigned int i = 0; i < SIZE; i++){
            if(hashArray[i] != NULL){
                Node* tmpNode = hashArray[i];
                Node* currentNode = hashArray[i];
                while(currentNode){
                    currentNode = currentNode->next;
                    delete tmpNode;
                    tmpNode = currentNode;
                }
            }
        }

        delete [] hashArray;
    }

    template<class V>
    V map<string, V>::generateHash(string first)
    {
        unsigned long hash = 0;
        for(unsigned int j = 0; j < first.length(); j++){
            hash += first[j];
        }
        return (V) hash % SIZE;
    }

    template<class V>
    void map<string, V>::checkHeadTail()
    {
        if(hashArray[0] != NULL){
            head = hashArray[0];
            tail = hashArray[0];
        }

        Node* currentNode = *hashArray;
        while(currentNode->next){
            currentNode = currentNode->next;
        }
        tail = currentNode;
    }

    template<class V>
    void map<string, V>::addPair(string first, V second)
    {
        Node* newEntry = new Node;
        newEntry->first = first;
        newEntry->second = second;
        newEntry->next = NULL;

        V hash = generateHash(first);

        if(hashArray[hash] == NULL){
            hashArray[hash] = newEntry;
            lastEntry = newEntry;
        } else {
            Node* currentNode = hashArray[hash];
            while(currentNode->next){
                if(currentNode->first == first){
                    currentNode->second += second;
                    lastEntry = currentNode;
                    return;
                }
                currentNode = currentNode->next;
            }
            if(currentNode->first == first){
                currentNode->second += second;
                lastEntry = currentNode;
                return;
            } else {
                currentNode->next = newEntry;
                lastEntry = newEntry;
                return;
            }
        }
        checkHeadTail();
    }

    template<class V>
    V& map<string, V>::operator[](string first)
    {
        V second = 0;
        addPair(first, second);

        return lastEntry->second;
        checkHeadTail();
    }

    template<class V>
    V map<string, V>::count(string key)
    {
        V hash = generateHash(key);
        if(hashArray[hash] != NULL){
            return true;
        }
        return false;
    }

    template<class V>
    map<string, V>::iterator::iterator()
    {
        currentNode = NULL;
    }

    template<class V>
    map<string, V>::iterator::iterator(Node* pos)
    {
        currentNode = pos;
    }

    template<class V>
    void map<string,V>::iterator::operator++(V)
    {
        currentNode = currentNode->next;
    }

    template<class V>
    typename map<string, V>::Node* map<string, V>::iterator::operator->()
    {
        return currentNode;
    }

    template<class V>
    bool map<string, V>::iterator::operator!=(map::iterator other)
    {
        if(first == other->first) return false; return true;
    }

} // END NAMESPACE

#endif // MAP_H

错误:

undefined reference to `myMap::map<std::string, int>::begin()'
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::end()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::begin()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::end()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|
undefined reference to `myMap::map<std::string, int>::iterator::~iterator()'|

当应用程序尝试使用迭代器时会发生错误:

map<string, int>::iterator iter;
for(iter = wordsCount.begin(); iter != wordsCount.end(); iter++){
    orderedList.addWord(iter->first, iter->second);
}

作为任务的一部分,我不能只更改上面的迭代器的使用,我必须自己创建它。

【问题讨论】:

  • 您会收到哪些函数的错误消息?您的示例错过了 map 函数的所有实现。只实现了map::iterator的成员函数。
  • 我已经更新了代码以反映整个文件。感谢您的快速回复:)
  • 我在您发布的内容中看不到begin()end()~iterator() 的实现,您确定这是整个文件吗?

标签: c++ templates reference iterator undefined


【解决方案1】:

导致错误消息的成员函数的实现不在map&lt;string, V&gt; 的头文件中。我在任何地方都看不到map::begin()map::end()map::iterator::~iterator() 的实现。大多数其他功能似乎都已实现(没有检查所有功能),但缺少这三个功能。 map&lt;K, V&gt; 在类内部实现了begin()end(),但那里也缺少iterator::~iterator() 的实现。

【讨论】:

  • 啊,这就是我得到重复错误的 3 个,谢谢。我会看看我能不能修复它们。我没有意识到我在专业化中删除了这些函数的内联声明。
  • 啊 - begin()end() 在类中定义。我错过了:)
  • 好的,我现在可以正常编译了,但是我一启动它就崩溃了……哈哈
  • 你知道我是否必须为迭代器清理析构函数中的任何东西,因为没有任何东西是动态分配的,所以它应该只是 emtpy 不应该吗?
  • 我不太了解iterator 中的firstsecond 成员。他们已经在Node 中。但除此之外,我没有看到你必须在析构函数中做任何事情,是的。但我没有阅读完整的代码。
猜你喜欢
  • 2017-06-20
  • 2018-05-13
  • 2011-05-07
  • 2015-11-19
  • 2022-01-24
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多