链接器错误无法通过一次编译所有文件来解决

时间:2014-02-02 21:05:06

标签: c++ linker g++

我正在编写一个用于创建Card对象链接列表的赋值,并且在编译时遇到了链接器错误。在Deck类cpp中,我获得了对重载<<<<<<<<运算符和Card的LinkedList构造函数。我尝试在Dev C ++和g ++中进行编译

在开发中我收到以下错误:

C:\Users\Chris\Dropbox\mohroo-2a\Deck.o Deck.cpp:(.text+0x1c): undefined reference to `operator<<(std::ostream&, LinkedList<Card> const&)'
C:\Users\Chris\Dropbox\mohroo-2a\Deck.o Deck.cpp:(.text+0x3e): undefined reference to `LinkedList<Card>::LinkedList()'
c:\program files (x86)\dev-cpp\mingw64\x86_64-w64-mingw32\bin\ld.exe            C:/Users/Chris/Dropbox/mohroo-2a/Deck.o: bad reloc address 0x0 in section `.pdata'
c:\program files (x86)\dev-cpp\mingw64\x86_64-w64-mingw32\bin\ld.exe    final link failed: Invalid operation
F:\Documents\collect2.exe   [Error] ld returned 1 exit status

在g ++中:

In file included from Deck.h:4:0,
             from Deck.cpp:1:
LinkedList.h:9:76: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const LinkedList<T>&)’ declares a non-template function [-Wnon-template-friend]
  friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<T> &l);
                                                                        ^
LinkedList.h:9:76: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
In file included from LinkedList.cpp:1:0:
LinkedList.h:9:76: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const LinkedList<T>&)’ declares a non-template function [-Wnon-template-friend]
  friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<T> &l);
                                                                        ^
LinkedList.h:9:76: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
In file included from Deck.h:4:0,
             from program.cpp:2:
LinkedList.h:9:76: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const LinkedList<T>&)’ declares a non-template function [-Wnon-template-friend]
  friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<T> &l);
                                                                        ^
LinkedList.h:9:76: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
/tmp/cc3tT0cD.o:Deck.cpp:(.text+0x1c): undefined reference to `operator<<(std::ostream&, LinkedList<Card> const&)'
/tmp/cc3tT0cD.o:Deck.cpp:(.text+0x1c): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `operator<<(std::ostream&, LinkedList<Card> const&)'
/tmp/cc3tT0cD.o:Deck.cpp:(.text+0x3e): undefined reference to `LinkedList<Card>::LinkedList()'
/tmp/cc3tT0cD.o:Deck.cpp:(.text+0x3e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `LinkedList<Card>::LinkedList()'
/usr/lib/gcc/x86_64-pc-cygwin/4.8.1/../../../../x86_64-pc-cygwin/bin/ld:     /tmp/cc3tT0cD.o: bad reloc address 0x0 in section `.pdata'
collect2: error: ld returned 1 exit status

以下是代码:

加入deck.h

#ifndef DECK_H
#define DECK_H
#include <ostream>
#include "LinkedList.h"
#include "Card.h"

class Deck
{
    friend std::ostream &operator<<(std::ostream &ostr, const Deck &d);

    public:
        Deck();

    private:
        LinkedList<Card> theDeck;
        Node<Card> *top;
};

#endif

Deck.cpp

#include "Deck.h"

std::ostream &operator<<(std::ostream &ostr, const Deck &d)
{
    ostr << d.theDeck;
    return ostr;
}

Deck::Deck()
{

}

LinkedList.h

#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <ostream>
#include "Node.h"

template <typename T>
class LinkedList
{

    template <typename K>
    friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<K> &l);

    public:
        LinkedList();
        ~LinkedList();
        void addNode(Node<T> *newNode);
        Node<T> *head;
};

template <typename T>
LinkedList<T>::LinkedList()
{
    head = 0;
}

template <typename T>
LinkedList<T>::~LinkedList()
{
    Node<T> *ptr = head;
    while(ptr != 0)
    {
        Node<T> *temp = ptr->next;
        delete ptr;
        ptr = temp;
    }
}

template <typename T>
void LinkedList<T>::addNode( Node<T> *newNode)
{
    Node<T> *ptr = head;
    while(ptr != 0)
    {
        ptr = ptr->next;
    }
    ptr->next = newNode;
}

template <typename K>
friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<K> &l)
{
    ostr << "[ ";
    Node<T> *ptr = l.head;
    while(ptr != 0)
    {
        ostr << ptr->data << " ";
        ptr = ptr->next;
    }
    ostr << "]";
    return ostr;
}

#endif

Node.h

#ifndef NODE_H
#define NODE_H

template <typename T>
class Node
{

    public:
        Node();
        Node(const T &nodeData);
        Node(const Node<T> *nextNode);
        Node(const T &nodeData, const Node *nextNode);

        T data;
        Node *next;

};

template <typename T>
Node<T>::Node()
    :data()
{
    next = 0;
}

template <typename T>
Node<T>::Node(const T &nodeData)
{
    data = nodeData;
    next = 0;
}

template <typename T>
Node<T>::Node(const Node<T> *nextNode)
    :data()
{
    next = nextNode;
}

template <typename T>
Node<T>::Node(const T &nodeData, const Node *nextNode)
{
    data = nodeData;
    next = nextNode;
}

#endif

Card.h

#ifndef CARD_H
#define CARD_H
#include <ostream>
class Card
{

      friend std::ostream &operator << (std::ostream &ostr, const Card &c);

      private:
            int value; //Ranges from 2-14, where Ace = 14, Jack = 11, Queen = 12, King = 13
            int suit; //Ranges from 1-4, where 1 = Clubs, 2 = Diamonds, 3 = Hearts, 4 = Spades

      public:
             Card();
             Card(int, int);
             Card operator=(const Card &crd);
             Card (const Card &obj);
             void setValue(int);
             void setSuit(int);
             int getValue();
             int getSuit();

};


#endif

Card.cpp

#include "Card.h"

std::ostream &operator<<(std::ostream &ostr, const Card &c)
{
    switch(c.value)
    {
    case 2:
        ostr << "Two";
        break;
    case 3:
        ostr << "Three";
        break;
    case 4:
        ostr << "Four";
        break;
    case 5:
        ostr << "Five";
        break;
    case 6:
        ostr << "Six";
        break;
    case 7:
        ostr << "Seven";
        break;
    case 8:
        ostr << "Eight";
        break;
    case 9:
        ostr << "Nine";
        break;
    case 10:
        ostr << "Ten";
        break;
    case 11:
        ostr << "Jack";
        break;
    case 12:
        ostr << "Queen";
        break;
    case 13:
        ostr << "King";
        break;
    case 14:
        ostr << "Ace";
        break;
    }
    ostr << " of ";

    switch(c.suit)
    {
    case 1:
        ostr << "Clubs";
        break;
    case 2:
        ostr << "Diamonds";
        break;
    case 3:
        ostr << "Hearts";
        break;
    case 4:
        ostr << "Spades";
        break;
    }
    return ostr;
}

Card::Card()
{
            value = 0;
            suit = 0;
};


Card::Card(const Card &obj)
{
                 value = obj.value;
                 suit = obj.suit;
};


Card Card::operator=(const Card &crd)
{
     suit = crd.suit;
     value = crd.value;

     return *this;
};


Card::Card(int tvalue, int tsuit)
{
               value = tvalue;
               suit = tsuit;
};


void Card::setValue(int tempValue)
{
     value = tempValue;
}


void Card::setSuit(int tempSuit)
{
     suit = tempSuit;
}


int Card::getValue()
{
    return value;
}


int Card::getSuit()
{
    return suit;
}

最后是program.cpp

#include <iostream>
#include "Deck.h"
using namespace std;

int main()
{
    Card someCard(2,4);
    Card otherCard(14,1);
    cout << someCard << "\n" << otherCard << endl;


}

那么任何想法?我试过看起来这看起来像链接器错误但是当我使用g++ *.cpp -o main进行编译时会产生上述错误。我接下来要做什么了。提前致谢

编辑:

LinkedList.h现在看起来像这样

#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <ostream>
#include "Node.h"

template <typename T>
class LinkedList
{
    template <typename K>
    friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<K> &l);


    public:
        LinkedList();
        ~LinkedList();
        void addNode(Node<T> *newNode);
        Node<T> *head;
};

template <typename T>
LinkedList<T>::LinkedList()
{
    head = 0;
}

template <typename T>
LinkedList<T>::~LinkedList()
{
    Node<T> *ptr = head;
    while(ptr != 0)
    {
        Node<T> *temp = ptr->next;
        delete ptr;
        ptr = temp;
    }
}

template <typename T>
void LinkedList<T>::addNode( Node<T> *newNode)
{
    Node<T> *ptr = head;
    while(ptr != 0)
    {
        ptr = ptr->next;
    }
    ptr->next = newNode;
}

template <typename K>
friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<K> &l)
{
    ostr << "[ ";
    Node<T> *ptr = l.head;
    while(ptr != 0)
    {
        ostr << ptr->data << " ";
        ptr = ptr->next;
    }
    ostr << "]";
    return ostr;
}

#endif

2 个答案:

答案 0 :(得分:2)

除了如上所述,模板必须在头文件中,实际问题是友元函数实际上不在类的范围内,所以你不能使用typename T,它可以隐藏类的类型名称。使用另一个,尝试K

template <typename T>
class LinkedList
{
    template <typename K>
    friend std::ostream &operator<<(std::ostream &ostr, const LinkedList<K> &l);
...

您仍然可以使用T来实现运算符。如果使用K:

template <typename K>
std::ostream &operator<<(std::ostream &ostr, const LinkedList<K> &l)
{
    ostr << "[ ";
    Node<K> *ptr = l.head;

答案 1 :(得分:0)

您应该在头文件中编写所有模板类。编译器在编译.cpp文件时不知道您将使用哪些类作为模板,因此它根本不生成任何内容。