2017-03-17 133 views
0

我想在C++中使用VS-2013實現一個紙牌遊戲,並且我有一個「Player」類。 「Player」類是抽象的,因爲該類的實際對象不會被初始化。相反,它只能繼承4個不同的玩家類別(有4種不同的玩法) - 「PlayerType1」到「PlayerType4」。C++錯誤錯誤C2512沒有適當的默認構造函數可用

這是我Player.h文件:

#ifndef PLAYER_H_ 
#define PLAYER_H_ 

#include <iostream> 
#include "Hand.h" 
using namespace std; 

class Player : public Hand { 
private: 
    const string name; 
protected: 
    Hand myHand; 
public: 
    string getName(); //Returns the name of the player 
    virtual int getShapeToAsk() = 0; 
    virtual int getPlayerToAsk() = 0; 
    virtual ~Player(); 
}; 

class PlayerType1 : public Player { //For strategy 1 
    PlayerType1(); 
    virtual int getShapeToAsk() override; 
    virtual int getPlayerToAsk() override; 
    ~PlayerType1(); 
}; 

class PlayerType2 : public Player { //For strategy 2 
    PlayerType2(); 
    virtual int getShapeToAsk() override; 
    virtual int getPlayerToAsk() override; 
    ~PlayerType2(); 
}; 

class PlayerType3 : public Player { //For strategy 3 
private: 
    int myNumber, numOfPlayers, nextPlayer; 
public: 
    PlayerType3(int myNumber, int numOfPlayers); 
    virtual int getShapeToAsk() override; 
    virtual int getPlayerToAsk() override; 
    ~PlayerType3(); 
}; 

class PlayerType4 : public Player { //For strategy 4 
private: 
    int myNumber, numOfPlayers, nextPlayer; 
public: 
    PlayerType4(int myNumber, int numOfPlayers); 
    virtual int getShapeToAsk() override; 
    virtual int getPlayerToAsk() override; 
    ~PlayerType4(); 
}; 

#endif 

這是我Player.cpp文件:

#include <iostream> 
#include <vector> 
#include "Hand.h" 
#include "Player.h" 
using namespace std; 

//Player functions 

string Player::getName(){ 
    return (this->name + " " + this->toString()); 
} 

Player::~Player(){} 

//PlayerType1 functions 

PlayerType1::PlayerType1(){} 

int PlayerType1::getShapeToAsk(){ 
    int maxCount = 0, maxValue, currValue, count; 
    for (std::vector<Card*>::reverse_iterator i = this->myHand.getCards().rbegin(); i != this->myHand.getCards().rend(); i++){ 
     count = 1; 
     currValue = (**i).getValue(); 
     for (i; (i != this->myHand.getCards().rend()) && ((**i).getValue() == currValue); ++i){ 
      count++; 
     } 
     if (count > maxCount){ 
      maxCount = count; 
      maxValue = currValue; 
      if (maxCount == 4) // no need to look at the rest of the hand 
       break; 
     } 
    } 
    return maxValue; 
} 

int PlayerType1::getPlayerToAsk(){ return -1; } //-1 means "I am a player of type 1 or 2". Game's responsibility to change later. 

PlayerType1::~PlayerType1(){} 

//PlayerType2 functions 

PlayerType2::PlayerType2(){} 

int PlayerType2::getShapeToAsk(){ 
    int minCount = 5, minValue, currValue, count; 
    for (std::vector<Card*>::iterator i = this->myHand.getCards().begin(); i != this->myHand.getCards().end(); i++){ 
     count = 1; 
     currValue = (**i).getValue(); 
     for (i; (i != this->myHand.getCards().end()) && ((**i).getValue() == currValue); ++i){ 
      count++; 
     } 
     if (count < minCount){ 
      minCount = count; 
      minValue = currValue; 
      if (minCount == 1) // no need to look at the rest of the hand 
       break; 
     } 
    } 
    return minValue; 
} 

int PlayerType2::getPlayerToAsk(){ return -1; } //-1 means "I am a player of type 1 or 2". Game's responsibility to change later. 

PlayerType2::~PlayerType2(){} 

//PlayerType3 functions 

PlayerType3::PlayerType3(int myNumber, int numOfPlayers){ 
    this->myNumber = myNumber; 
    this->numOfPlayers = numOfPlayers; 
    if (myNumber == 1) this->nextPlayer = 2; 
    else this->nextPlayer = 1; 
} 

int PlayerType3::getShapeToAsk(){ 
    int maxCount = 0, maxValue, currValue, count; 
    for (std::vector<Card*>::reverse_iterator i = this->myHand.getCards().rbegin(); i != this->myHand.getCards().rend(); i++){ 
     count = 1; 
     currValue = (**i).getValue(); 
     for (i; (i != this->myHand.getCards().rend()) && ((**i).getValue() == currValue); ++i){ 
      count++; 
     } 
     if (count > maxCount){ 
      maxCount = count; 
      maxValue = currValue; 
      if (maxCount == 4) // no need to look at the rest of the hand 
       break; 
     } 
    } 
    return maxValue; 
} 

int PlayerType3::getPlayerToAsk(){ 
    int temp = this->nextPlayer; 
    this->nextPlayer++; 
    while ((this->nextPlayer == this->myNumber) || (this->nextPlayer > this->numOfPlayers)){ 
     if (this->nextPlayer == this->myNumber) this->nextPlayer++; 
     if (this->nextPlayer > this->numOfPlayers) this->nextPlayer = 1; 
    } 
    return temp; 
} 

PlayerType3::~PlayerType3(){} 

//PlayerType4 functions 

PlayerType4::PlayerType4(int myNumber, int numOfPlayers){ 
    this->myNumber = myNumber; 
    this->numOfPlayers = numOfPlayers; 
    if (myNumber == 1) this->nextPlayer = 2; 
    else this->nextPlayer = 1; 
} 

int PlayerType4::getShapeToAsk(){ 
    int minCount = 5, minValue, currValue, count; 
    for (std::vector<Card*>::iterator i = this->myHand.getCards().begin(); i != this->myHand.getCards().end(); i++){ 
     count = 1; 
     currValue = (**i).getValue(); 
     for (i; (i != this->myHand.getCards().end()) && ((**i).getValue() == currValue); ++i){ 
      count++; 
     } 
     if (count < minCount){ 
      minCount = count; 
      minValue = currValue; 
      if (minCount == 1) // no need to look at the rest of the hand 
       break; 
     } 
    } 
    return minValue; 
} 

int PlayerType4::getPlayerToAsk(){ 
    int temp = this->nextPlayer; 
    this->nextPlayer++; 
    while ((this->nextPlayer == this->myNumber) || (this->nextPlayer > this->numOfPlayers)){ 
     if (this->nextPlayer == this->myNumber) this->nextPlayer++; 
     if (this->nextPlayer > this->numOfPlayers) this->nextPlayer = 1; 
    } 
    return temp; 
} 

PlayerType4::~PlayerType4(){} 

我收到以下錯誤:

Error  error C2512: 'Player' : no appropriate default constructor available <PATH>\player.cpp 

共該類型的4個錯誤,每個指向PlayerType1到PlayerType4的構造函數。

當我向我的「Player」類中添加一個空的默認構造函數時,它解決了問題,並且我獲得了成功的構建。 但是,我看不出爲什麼我需要爲「Player」類定義默認構造函數,因爲我從不初始化該類的對象。

我還應該提到我的項目中有另一個類(「卡」類),它是抽象的,只是在那裏被其他類繼承(「圖卡」和「數字卡片」),也沒有構造函數,派生類有它們自己的構造函數,並且不會導致錯誤。我看不出有什麼不同。

我搜索了其他問題,但它們都涉及未定義默認構造函數的情況,以及代碼中其他地方嘗試初始化該類的情況。這不是我的情況,因爲我沒有初始化類「Player」的對象,只有4個派生類。

請幫忙! 預先感謝您。

回答

1

即使你的Player類是抽象的,你必須定義一個構造函數,因爲你的類有成員。當您創建派生類(任何您的PlayerType)類的實例時,它將調用基類的構造函數。這就是繼承是如何工作的...

在這種情況下,將它保護起來(因爲它是一個純虛擬類,所以它是公共的將毫無用處)。

0

您的Player班有一個private: const string name;成員。看看你的Card課;我敢打賭,它沒有這樣的成員。這是不同的。

事情是,const string name;成員必須以某種方式初始化,並且因爲它是private,它必須在Player類中初始化。 (語言規則禁止從派生類中初始化類的私有成員。)因此,Player類必須具有將初始化name成員的構造函數。空的構造函數實現了這一點。

+0

謝謝!刪除「const」這個詞確實解決了這個問題,這也是我的「玩家」和「卡」類之間的區別。 – Gil

+0

我確實有一個問題。如果我爲剛剛初始化「const string name」變量的「Player」類構造一個構造函數,併爲我的派生類構造一個構造函數,我該如何去啓動「名稱」和其他與派生相關的事情班?假設我想讓「名稱」變量在「播放器」中保留一個私有的變量。 – Gil

+0

如果我正確理解你想做什麼,你需要的只是從派生類中調用基礎構造函數。這就是DerivedClass():BaseClass(){...'< - 這是'DerivedClass'的構造函數調用'BaseClass()'的構造函數。 –

相關問題