87

誰かがこれを手伝ってくれるかどうか疑問に思っていました-私はC ++を初めて使用しただけで、かなりの問題を引き起こしています。

比較的単純な Deck および Card クラス オブジェクトを作成しようとしています。

「Deck.cpp」、カードの配列の宣言、および配列にカード オブジェクトを入力しようとすると、エラーが表示されます。Card::Card()Card::Card(Card::Rank, Card::Suit)およびへの未定義の参照があると表示されCard::~Card()ます。

インクルードはすべて正しいように見えるので、何が問題なのかわかりません。

コードは次のとおりです。

デッキ.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

デッキ.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;
}
4

4 に答える 4

82

これをコンパイルするために何を使用していますか?未定義の参照エラーがある場合、通常は (.cpp ファイルから作成される) .o ファイルが存在せず、コンパイラ/ビルド システムがそれをリンクできないことが原因です。

また、card.cpp では、関数は のCard::Card()代わりにある必要がありvoid Cardます。はスコープCard::です。これは、関数が Card クラスのメンバーであることを意味します(これは、そのクラスのコンストラクタであるため、明らかにそうです)。これがなければ、void Card はただの無料機能です。同様に、Card()

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

する必要があります

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

また、deck.cppではdeck.hと呼んでいるのに言っ#include "Deck.h"ている。インクルードでは大文字と小文字が区別されます。

于 2013-03-29T23:21:25.737 に答える
13

Cardクラスの定義では、デフォルトの構築の宣言が表示されます。

class Card
{
    // ...

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

    // ...
};

しかし、対応する定義はありません。実際、この関数定義 (からcard.cpp):

void Card() {
//nothing
}

コンストラクタを定義するのではなくCard、を返すグローバル関数を定義しますvoid。あなたはおそらく代わりにこれを書くつもりでした:

Card::Card() {
//nothing
}

そうしないと、既定のコンストラクターは宣言されているが定義されていないため、リンカーは、既定のコンストラクターへの呼び出しが見つかったときに、未定義の参照に関するエラーを生成します。


2 つの引数を受け取るコンストラクターにも同じことが当てはまります。これ:

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

これに書き換える必要があります:

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

Card::同じことが他のメンバー関数にも当てはまります。定義のメンバー関数名の前に修飾子を追加しなかったようです。それがなければ、それらの関数はメンバー関数の定義ではなくグローバル関数になります。


一方、デストラクタは宣言されていますが、定義されていません。で定義を提供するだけですcard.cpp

Card::~Card() { }
于 2013-03-29T23:14:15.293 に答える
3

この部分には問題があります:

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は動的配列ですが、Cardクラスのメンバーではありません。クラスのメンバーではない動的配列を初期化したい場合は奇妙です
  2. void Deck()スコープ解決演算子を逃したため、クラス Deck のコンストラクターではありません。Deckコンストラクターと関数を nameと return typeで定義すると混乱するかもしれませんvoid
  3. あなたのループでは、それ以外の場合は使用し<ないでください>。ループは実行されません。
于 2013-03-29T23:21:03.047 に答える
1

コンストラクターのクラス カードを指定します。

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

また、デフォルトのコンストラクタとデストラクタも定義します。

于 2013-03-29T23:14:43.343 に答える