2013-03-29 21 views
31

Ich fragte mich, ob mir jemand dabei helfen könnte - ich bin erst neu in C++ und es verursacht mir eine ganze Menge Probleme.C++ - Fehler 'Undefinierter Verweis auf Class :: Function()'

Ich versuche, relativ einfache Deck und Card Klassenobjekte zu machen.

Der Fehler wird in "Deck.cpp" angezeigt, Deklaration eines Arrays von Karten, und wenn ich dann versuche, das Array mit Kartenobjekten zu füllen. Dort steht ein undefinierter Verweis auf Card::Card(), Card::Card(Card::Rank, Card::Suit) und Card::~Card().

Ich habe alle meine Includes scheinbar richtig, also weiß ich nicht, was schief läuft.

Der Code lautet wie folgt:

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; 
} 

Antwort

26

Was verwenden Sie, um dies zu kompilieren? Wenn ein nicht definierter Referenzfehler vorliegt, liegt dies normalerweise daran, dass die .o-Datei (die aus der CPP-Datei erstellt wird) nicht existiert und Ihr Compiler/Build-System nicht in der Lage ist, sie zu verknüpfen.

Auch in Ihrer card.cpp sollte die Funktion Card::Card() statt void Card sein. Die Card:: ist Scoping; es bedeutet, dass Ihre Card() Funktion ein Mitglied der Card-Klasse ist (was es offensichtlich ist, da es der Konstruktor für diese Klasse ist). Ohne diese Funktion ist void Card nur eine kostenlose Funktion. In ähnlicher Weise

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

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

auch sein sollte, in deck.cpp, sagen Sie #include "Deck.h" obwohl Sie als deck.h. ihm vorgelegten Bei den Includes wird zwischen Groß- und Kleinschreibung unterschieden

8

In der Definition Ihrer Card Klasse, eine Erklärung für eine Standardkonstruktion erscheint:

class Card 
{ 
    // ... 

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

    // ... 
}; 

aber keine entsprechende Definition gegeben. In der Tat, diese Funktionsdefinition (von card.cpp):

void Card() { 
//nothing 
} 

Hat nicht einen Konstruktor definieren, sondern eine globale Funktion Card genannt, die void zurückgibt. Sie wahrscheinlich bedeutete dies stattdessen zu schreiben:

Card::Card() { 
//nothing 
} 

Wenn Sie das tun, da der Standard-Konstruktor deklariert, aber nicht definiert ist, der Linker Fehler über undefinierte Referenzen erzeugt, wenn ein Aufruf der Standard-Konstruktor gefunden wird.


Das Gleiche gilt für Ihren Konstruktor, der zwei Argumente akzeptiert. Dies:

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

Sollte in diese neu geschrieben werden:

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

Und das gleiche gilt auch für andere Mitgliedsfunktionen: es scheint, dass Sie die Card:: Qualifier vor den Mitgliedsfunktionsnamen in ihren Definitionen nicht hinzugefügt haben. Ohne sie sind diese Funktionen globale Funktionen und keine Definitionen von Elementfunktionen.


Ihr Destruktor dagegen ist deklariert, aber nie definiert.Geben Sie einfach eine Definition für sie in card.cpp:

Card::~Card() { } 
+0

Müssen alle Funktionsdefinitionen in der CPP-Datei so aussehen? z.B. Karte :: Rangkarte :: GetRank() { return cardRank; } Karte :: Anzugkarte :: GetSuit() { return cardSuit; } –

+1

@BenHarris: Ja, so definieren Sie Member-Funktionen –

0

die Klasse Karte für den constructor- angeben:

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

Und auch die Standard-Konstruktor und Destruktor definieren.

3

Dieser Teil hat Probleme:

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 ein dynamisches Array ist, aber kein Mitglied der Klasse Card. Es ist merkwürdig, wenn Sie ein dynamisches Array initialisieren möchten, das kein Mitglied der Klasse
  2. void Deck() ist, ist nicht Konstruktor der Klasse Deck seit Sie den Bereich Auflösung-Operator verpasst haben. Sie können verwirrt sein, wenn Sie den Konstruktor und die Funktion mit dem Namen Deck definieren und den Typ void zurückgeben.
  3. in Ihren Schleifen, sollten Sie < nicht > sonst verwenden, Schleife wird nie ausgeführt werden.
Verwandte Themen