I'm working on an assignment to make a linked list of Card objects, and I'm running into a linker error when compiling. In the Deck class cpp, I get an udefined reference to the overloaded << operator and to the LinkedList constructor for Card. I've tried compiling in both Dev C++ and g++
In dev I get the following error:
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
in 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
Here is the code:
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;
}
and lastly 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;
}
So any ideas? I've tried looking this up and it seems like a linker error but when I compile using g++ *.cpp -o main
it produces the above error. I've hit a wall with what to do next. Thanks in advance
EDIT:
LinkedList.h now looks like this
#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