誰かがこれを手伝ってくれるかどうか疑問に思っていました-私は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;
}
これをコンパイルするために何を使用していますか?未定義の参照エラーがある場合、通常は.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"
と言っています。インクルードでは大文字と小文字が区別されます。
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() { }
この部分には問題があります:
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++;
}
}
}
cardArray
は動的配列ですが、Card
クラスのメンバーではありません。クラスのメンバーではない動的配列を初期化する場合は奇妙ですvoid Deck()
は、スコープ解決演算子を逃したため、Deckクラスのコンストラクタではありません。名前Deck
と戻り値の型void
を持つコンストラクターと関数の定義と混同される可能性があります。<
ではなく>
を使用する必要があります。そうでない場合、ループは実行されません。コンストラクターのクラスカードを指定します。
void Card::Card(Card::Rank rank, Card::Suit suit) {
また、デフォルトのコンストラクタとデストラクタも定義します。