C++ error 'Undefined reference to Class::Function()'

C++OopUndefined

C++ Problem Overview


I was wondering if anyone could help me out with this - I'm only new to C++ and it's causing me a fair amount of troubles.

I'm trying to make relatively simple Deck and Card class objects.

The error is showing up in "Deck.cpp", declaration of an array of cards, and then when i try to fill the array with card objects. It says there's an undefined reference to Card::Card(), Card::Card(Card::Rank, Card::Suit) and Card::~Card().

I've got all my includes seemingly right, so I don't know what's going wrong.

The code is as follows:

deck.h

#ifndef DECK_H
#define DECK_H
#include "card.h"

class Deck
{
 public:
    Deck();
    ~Deck();
    Card DealNextCard();
    void Shuffle();
    void DisplayDeck();
protected:
private:

};

#endif // DECK_H

deck.cpp

#include "Deck.h"
#include "card.h"

using namespace std;

const int NUM_TOTAL_CARDS = 52;
const int NUM_SUITS = 4;
const int NUM_RANKS = 13;
Card* cardArray;
void Deck() {
    cardArray = new Card[NUM_TOTAL_CARDS];
    int cardCount = 0;
    for (int i = 0; i > NUM_SUITS; i++) {
        for (int j = 0; j > NUM_RANKS; j++) {
            cardArray[cardCount] = Card(Card::Rank(i), Card::Suit(j) );
            cardCount++;
        }
    }
}


Card DealNextCard();
void Shuffle();
void DisplayDeck();

card.h

class Card
{

    public:
        enum Suit {D=0, H, C, S};
        enum Rank {ONE=0, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, J, Q, K, A};
        Card(Card::Rank, Card::Suit);
        Card();
        virtual ~Card();
        Card::Suit suit;
        Card::Rank rank;
        Card::Rank GetRank();
        Card::Suit GetSuit();
        std::string CardName();

    protected:

    private:

};

#endif // CARD_H

card.cpp

#include "card.h"
using namespace std;


Card::Suit cardSuit;
Card::Rank cardRank;

void Card() {
    //nothing
     }


void Card(Card::Rank rank, Card::Suit suit) {
cardRank = rank;
cardSuit = suit;
}

Card::Rank GetRank() {
return cardRank;
}
Card::Suit GetSuit() {
return cardSuit;
}
std::string CardName() {
    string test;
    test = "testing string";
    return test;
}

C++ Solutions


Solution 1 - C++

What are you using to compile this? If there's an undefined reference error, usually it's because the .o file (which gets created from the .cpp file) doesn't exist and your compiler/build system is not able to link it.

Also, in your card.cpp, the function should be Card::Card() instead of void Card. The Card:: is scoping; it means that your Card() function is a member of the Card class (which it obviously is, since it's the constructor for that class). Without this, void Card is just a free function. Similarly,

void Card(Card::Rank rank, Card::Suit suit)

should be

Card::Card(Card::Rank rank, Card::Suit suit)

Also, in deck.cpp, you are saying #include "Deck.h" even though you referred to it as deck.h. The includes are case sensitive.

Solution 2 - C++

In the definition of your Card class, a declaration for a default construction appears:

class Card
{
    // ...

    Card(); // <== Declaration of default constructor!

    // ...
};

But no corresponding definition is given. In fact, this function definition (from card.cpp):

void Card() {
//nothing
}

Does not define a constructor, but rather a global function called Card that returns void. You probably meant to write this instead:

Card::Card() {
//nothing
}

Unless you do that, since the default constructor is declared but not defined, the linker will produce error about undefined references when a call to the default constructor is found.


The same applies to your constructor accepting two arguments. This:

void Card(Card::Rank rank, Card::Suit suit) {
    cardRank = rank;
    cardSuit = suit;
}

Should be rewritten into this:

Card::Card(Card::Rank rank, Card::Suit suit) {
    cardRank = rank;
    cardSuit = suit;
}

And the same also applies for other member functions: it seems you did not add the Card:: qualifier before the member function names in their definitions. Without it, those functions are global functions rather than definitions of member functions.


Your destructor, on the other hand, is declared but never defined. Just provide a definition for it in card.cpp:

Card::~Card() { }

Solution 3 - C++

This part has problems:

Card* cardArray;
void Deck() {
    cardArray = new Card[NUM_TOTAL_CARDS];
    int cardCount = 0;
    for (int i = 0; i > NUM_SUITS; i++) {  //Error
        for (int j = 0; j > NUM_RANKS; j++) { //Error
            cardArray[cardCount] = Card(Card::Rank(i), Card::Suit(j) );
            cardCount++;
         }
    }
 }
  1. cardArray is a dynamic array, but not a member of Card class. It is strange if you would like to initialize a dynamic array which is not member of the class
  2. void Deck() is not constructor of class Deck since you missed the scope resolution operator. You may be confused with defining the constructor and the function with name Deck and return type void.
  3. in your loops, you should use < not > otherwise, loop will never be executed.

Solution 4 - C++

Specify the Class Card for the constructor-:

void Card::Card(Card::Rank rank, Card::Suit suit) {

And also define the default constructor and destructor.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBen HarrisView Question on Stackoverflow
Solution 1 - C++madityaView Answer on Stackoverflow
Solution 2 - C++Andy ProwlView Answer on Stackoverflow
Solution 3 - C++taocpView Answer on Stackoverflow
Solution 4 - C++suspectusView Answer on Stackoverflow