web-dev-qa-db-ja.com

C ++エラー 'Class :: Function()への未定義参照'

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

比較的単純なデッキおよびカードクラスオブジェクトを作成しようとしています。

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

私は自分のインクルードをすべて一見正しく持っているので、何が間違っているのか分かりません。

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

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;
}
52
Ben Harris

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

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

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

あるべき

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

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

46
maditya

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

class Card
{
    // ...

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

    // ...
};

ただし、対応するdefinitionは指定されていません。実際、この関数定義(card.cppから):

void Card() {
//nothing
}

notはコンストラクタを定義しますが、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() { }
10
Andy Prowl

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

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と戻り値の型voidを持つコンストラクターと関数の定義と混同される可能性があります。
  3. ループでは、<ではなく>を使用する必要があります。そうでない場合、ループは実行されません。
3
taocp

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

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

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

1
suspectus