尝试制作派生类,编译器需要抽象基的默认构造函数
Trying to make derived class, compiler expects default constructor for abstract base
我们正在尝试创建一个抽象类"Game"和派生类"FiveCardDraw"。FiveCardDraw 的构造函数希望有一个默认的 Game 构造函数,但是我们的 Game 类不能有一个默认的构造函数,因为我们有纯虚拟方法。解决方案是什么?
我们的错误看起来像C:\users\Wesley\documents\Visual Studio 2010\projects\lab4\lab4\fivecarddraw.cpp(14):错误 C2512:"游戏":没有可用的适当默认构造函数
游戏.h
#ifndef GAME_H
#define GAME_H
#include "stdafx.h"
#include <string>
#include <vector>
#include "Player.h"
#include "Deck.h"
struct Player;
class Deck;
class Game{
protected:
Deck mainDeck;
vector<Player*> players;
static Game* game;
public:
static Game* instance();
static void start_game(const string&);
static void stop_game();
void addPlayer(const string&);
Player* find_player(const string&);
virtual ~Game();
virtual int before_turn(Player&)=0;
virtual int turn(Player&)=0;
virtual int after_turn(Player&)=0;
virtual int round()=0;
virtual int before_round()=0;
virtual int after_round()=0;
private:
Game(Game&);
void operator=(Game&);
};
#endif
游戏.cpp
#include "stdafx.h"
#include <string>
#include <vector>
#include "Player.h"
#include "Deck.h"
#include "Game.h"
#include "FiveCardDraw.h"
using namespace std;
static const int INSTANCE_NOT_AVAILABLE_ERROR=12;
static const int GAME_ALREADY_STARTED_ERROR=13;
static const int UNKNOWN_GAME_ERROR=14;
static const int NO_GAME_IN_PROGRES_ERROR=15;
static const int ALREADY_PLAYING_ERROR=16;
Game* Game::instance(){
if(game==0){
throw INSTANCE_NOT_AVAILABLE_ERROR;
}
else{
return game;
}
}
void Game::start_game(const string& gameType){
if(game!=0){
throw GAME_ALREADY_STARTED_ERROR;
}else if(gameType.find("FiveCardDraw")!=string::npos){
game = new FiveCardDraw();
}
else{
throw UNKNOWN_GAME_ERROR;
}
}
void Game::stop_game(){
if(game==0){
throw NO_GAME_IN_PROGRES_ERROR;
}
else{
delete game;
game=0;
}
}
void Game::addPlayer(const string& playerName){
for(unsigned int i=0; i<players.size();++i){
if(playerName==players[i]->Name){
throw ALREADY_PLAYING_ERROR;
}
}
players.push_back(new Player(playerName));
}
Player* Game::find_player(const string& playerName){
for(unsigned int i=0; i<players.size();++i){
if(playerName==players[i]->Name){
return players[i];
}
}
return 0;
}
Game::~Game(){
for(unsigned int i=0; i<players.size();++i){
delete players[i];
}
}
五张牌抽奖.h
#ifndef FIVECARDDRAW_H
#define FIVECARDDRAW_H
#include "stdafx.h"
#include <string>
#include <vector>
#include "Player.h"
#include "Deck.h"
#include "Game.h"
class FiveCardDraw : public Game {
protected:
unsigned int size_t;
Deck discardDeck;
public:
FiveCardDraw();
virtual int before_turn(Player &);
virtual int turn (Player &);
virtual int after_turn (Player &);
virtual int before_round();
virtual int round();
virtual int after_round();
};
#endif
五张牌抽奖.cpp
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include "FiveCardDraw.h"
#include "Card.h"
using namespace std;
static const int NUM_SUITS=4;
static const int NUM_RANKS=13;
static const int CARDS_PER_HAND =5;
static const int NOT_ENOUGH_CARDS_ERROR=16;
FiveCardDraw::FiveCardDraw() {
size_t = 0;
//nested for loop to generate all 52 possible cards
for(unsigned int s=0; s<NUM_SUITS; ++s){
for(unsigned int r=0; r<NUM_RANKS; ++r){
mainDeck.addCard( Card(Card::rank_(r),Card::suit_(s)));
}
}
}
int FiveCardDraw::before_turn(Player & player){
cout<<player.Name<<" has "<<player.myHand;
cout<<endl;
string toDiscard="";
while(toDiscard!="none"){
cout<<"Enter the number of a card you wish to discard (0-4) or "none" if you are done discarding."<<endl;
cin>>toDiscard;
if(toDiscard=="0" || toDiscard=="1" ||toDiscard=="2" || toDiscard=="3" || toDiscard=="4"){
unsigned int intToDiscard=stoi(toDiscard);
if(intToDiscard<toDiscard.size()){
discardDeck.addCard(player.myHand[intToDiscard]);
player.myHand.remove_card(intToDiscard);
}
else{
cout<<"There is no longer a card at position "<<intToDiscard<<"."<<endl;
}
}
}
return 0;
}
int FiveCardDraw::turn (Player & player){
unsigned int numCardsToReplace=CARDS_PER_HAND-player.myHand.size();
if(mainDeck.size()+discardDeck.size()<numCardsToReplace){
return NOT_ENOUGH_CARDS_ERROR;
}
if(mainDeck.size()<numCardsToReplace){
discardDeck.shuffle();
for(unsigned int i=0; i<numCardsToReplace; ++i){
mainDeck.addCard(discardDeck.removeCard());
}
}
while(player.myHand.size()<CARDS_PER_HAND){
player.myHand<<mainDeck;
}
return 0;
}
int FiveCardDraw::after_turn (Player & player){
cout<<player.Name<<" now has "<<player.myHand;
cout<<endl;
return 0;
}
int FiveCardDraw::before_round(){
return 0;
}
int FiveCardDraw::round(){
return 0;
}
int FiveCardDraw::after_round(){
return 0;
}
编译器
将为您提供一个空的默认构造函数,除非您声明自己的构造函数。 你做到了。
如果不先创建所有子对象(包括基类的子对象),则无法创建派生类。 为此需要一个构造函数。
protected:
Game() {}
请注意,如果要禁用复制,仍应使用普通签名。
private:
Game(const /* <- right there */ Game&);
在 C++11 中,您可以更明确地告诉编译器您希望阻止复制:
Game(const Game&) = delete;
同样,对于默认构造函数,您可以告诉编译器您确实希望它自动生成一个:
Game() = default;
FiveCardDraw 的构造函数希望有一个默认的 Game 构造函数,但是我们的 Game 类不能有一个默认的构造函数,因为我们有纯虚拟方法。解决方案是什么?
拥有抽象类并不意味着不能定义或使用构造函数,它只是意味着创建该类型对象的唯一方法是作为基类子对象。
所以继续为Game::Game()
定义一个合适的构造函数,然后从 mem-initializer-list of FiveCardDraw
中使用它。 也许它就像
Game::Game()
: mainDeck(),
players()
{}
FiveCardDraw::FiveCardDraw()
: Game(),
size_t(0),
discardDeck()
{}
或者,也许您需要一些参数来初始化Deck
成员....
顺便说一下,size_t
对于成员来说是一个糟糕的名字,因为std::size_t
是一种类型。
相关文章:
- 抽象类和构造函数
- C++的抽象类继承和构造函数的问题
- 自定义异常中的用户定义的空构造函数,具有多个继承和抽象基类
- C++:在共享对象中调用抽象基类构造函数/未定义的符号
- C++ 抽象类构造函数调用
- 抽象类和虚拟构造函数的替代方案
- 抽象类的复制构造函数中的问题
- C++ 接受对抽象类的常量引用的构造函数无法初始化 std::map
- C++:正确初始化抽象类的构造函数
- 如何使用继承(抽象基类)实现移动构造函数和移动赋值运算符
- 具有数据成员、构造函数和运算符重载的抽象基类
- 使用其他类中抽象类的构造函数
- C++ Qt 5 中构造函数的抽象类错误
- C++中抽象成员和类函数指针的深层复制构造函数
- 检测(可能是抽象的)基类的受保护构造函数
- C++做一个没有任何数据字段的抽象类需要一个构造函数
- 带有抽象类的unique_ptr成员和Copy构造函数的Factory方法模式
- 尝试制作派生类,编译器需要抽象基的默认构造函数
- 确定抽象基类的构造函数是否为 noexcept
- 在抽象构造函数/析构函数中调用纯虚拟函数安全吗