2013-03-29 32 views
31

Tôi đã tự hỏi liệu có ai có thể giúp tôi với điều này không - tôi mới chỉ với C++ và nó gây ra cho tôi một số rắc rối.Lỗi C++ 'Không xác định tham chiếu đến Lớp :: Chức năng()'

Tôi đang cố gắng tạo các đối tượng Lớp và Thẻ tương đối đơn giản.

Lỗi hiển thị trong "Deck.cpp", khai báo một mảng thẻ và sau đó khi tôi cố gắng lấp đầy mảng bằng các đối tượng thẻ. Nó cho biết có một tham chiếu không xác định đối với Card::Card(), Card::Card(Card::Rank, Card::Suit)Card::~Card().

Tôi đã có tất cả nội dung của tôi có vẻ đúng, vì vậy tôi không biết điều gì đang xảy ra.

Mã này là như sau:

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

Trả lời

26

Bạn đang sử dụng gì để biên dịch điều này? Nếu có lỗi tham chiếu không xác định, thường là do tệp .o (được tạo từ tệp .cpp) không tồn tại và hệ thống biên dịch/xây dựng của bạn không thể liên kết nó.

Ngoài ra, trong thẻ của bạn.cpp, chức năng phải là Card::Card() thay vì void Card. Card::phạm vi; nó có nghĩa là hàm Card() của bạn là một thành viên của lớp Thẻ (mà nó rõ ràng là, vì nó là hàm tạo cho lớp đó). Nếu không có điều này, Thẻ void chỉ là một chức năng miễn phí. Tương tự như vậy,

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

nên

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

Ngoài ra, trong deck.cpp, bạn đang nói #include "Deck.h" mặc dù bạn gọi nó như deck.h. Bao gồm phân biệt chữ hoa chữ thường.

8

Trong định nghĩa của lớp Card của bạn, một khai cho một công trình mặc định xuất hiện:

class Card 
{ 
    // ... 

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

    // ... 
}; 

Nhưng không tương ứng nét được đưa ra. Trong thực tế, định nghĩa này chức năng (từ card.cpp):

void Card() { 
//nothing 
} 

Liệu không định nghĩa một constructor, mà là một chức năng toàn cầu gọi Card trả void. Bạn có thể có nghĩa là để viết những dòng này thay vì:

Card::Card() { 
//nothing 
} 

Trừ khi bạn làm điều đó, kể từ khi các nhà xây dựng mặc định được khai báo nhưng không được xác định, các mối liên kết sẽ tạo ra lỗi về tài liệu tham khảo không xác định khi một cuộc gọi đến constructor mặc định sẽ được tìm thấy.


Điều tương tự cũng áp dụng cho nhà xây dựng của bạn chấp nhận hai đối số. Đây:

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

nên được viết lại thành này:

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

Và tương tự cũng áp dụng cho các chức năng thành viên khác: có vẻ như bạn đã không thêm Card:: vòng loại trước tên hàm thành viên trong định nghĩa của chúng. Không có nó, các chức năng đó là các chức năng toàn cầu hơn là các định nghĩa của các hàm thành viên.


Mặt khác, phá hủy của bạn được khai báo nhưng không bao giờ được xác định.Chỉ cần cung cấp một định nghĩa cho nó trong card.cpp:

Card::~Card() { } 
+0

Tất cả các định nghĩa chức năng phải như thế này, trong tệp CPP? ví dụ: Thẻ :: Thẻ xếp hạng :: GetRank() { thẻ trả lạiRank; } Thẻ :: Thẻ phù hợp :: GetSuit() { thẻ trả vềSuit; } –

+1

@BenHarris: Vâng, đó là cách bạn xác định chức năng của thành viên –

0

Xác định thẻ Class cho các constructor-:

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

Và cũng xác định constructor mặc định và destructor.

3

phần này có vấn đề:

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 là một mảng năng động, nhưng không phải là một thành viên của Card lớp. Thật lạ nếu bạn muốn khởi tạo mảng động không phải là thành viên của lớp
  2. void Deck() không phải là hàm tạo của lớp Lớp vì bạn đã bỏ lỡ toán tử phân giải phạm vi . Bạn có thể nhầm lẫn với việc xác định hàm tạo và hàm có tên Deck và trả về kiểu void.
  3. trong vòng của bạn, bạn nên sử dụng < không > nếu không, vòng lặp sẽ không bao giờ được thực thi.
Các vấn đề liên quan