2015-11-04 60 views
0

我在學習多態,這是一個小遊戲。我在這裏有一個代表性的角色角色,我想要編程,以便角色人們可以選擇戰士或弓箭手來繼續遊戲。關於C++中的多態性

#pragma once 
#include <iostream> 
using namespace std; 
#include <string> 

class Warrior; 
class Archer; 

class Character { 
    public: 
    Character(void); 
    ~Character(void); 

Character* creatCharacter(int choice, string CharacterName) { 

    if (choice == 1) 
     return (Character*)new Warrior(CharacterName); 

    if (choice == 2) 
     return (Character*)new Archer(CharacterName); 

     return NULL; 
    } 

    virtual void Skill_Cast() {}; 
}; 

class Warrior :public Character { 
private: 
    string name; 
public: 
    Warrior(void); 
    ~Warrior(void); 

    Warrior(string CharacterName) { 
     name = CharacterName; 
    } 


    void Skill_Cast() { 
     cout << "Punch!" << endl; 
    } 

}; 

class Archer : public Character 
{ 
private: 
    string name; 
public: 
Archer(void); 
~Archer(void); 

Archer(string CharacterName) { 
    name = CharacterName; 
} 

    void Skill_Cast() { 
    cout << "Shoot!" << endl; 
    } 

}; 

在主要功能:

int main() { 
    cout <<"Enter character's name: "; 
    string name; 
    getline(cin, name, '\n'); 
    cout <<"Enter your character class by number (1),(2),(3): "; 
    int choice; 
    cin >> choice; 

    Character* YourChar; 



    YourChar = YourChar->creatCharacter(choice, name); 

    YourChar->Skill_Cast(); 
} 

這是錯誤:

Error 1 error C2512: 'Warrior' : class has no constructors 
Error 2 error C2514: 'Archer' : class has no constructors 

你能解釋一下我的錯誤,並幫助我解決這個問題,順便說一下,這是一個一種「抽象工廠設計模式」?非常感謝。 (對不起,因爲我的英文不好)

+1

在聲明之前,你正在使用戰士和弓箭手。 –

+1

'return(Character *)new Warrior(CharacterName);'是不必要的,只是說'return new Warrior(CharacterName);' 又是什麼'NhanVat'? – rlbond

+0

在'YourChar-> creatCharacter'行上,您使用的是未初始化的指針。但是這並不能解釋錯誤信息。 – 5gon12eder

回答

0

將你的文件重新排列成標題/源文件。它會讓你的代碼更清晰,更易於閱讀,並且也可以解決你的問題。

// Archer.h 
#pragma once 

#include "Character.h" 

class Archer : public Character 
{ 
public: 
    Archer(void); 
    Archer(std::string CharacterName); 
    ~Archer(void); 

    void Skill_Cast(); 

private: 
    std::string name; 
}; 

// Character.h 
#pragma once 

#include <string> 

class Character 
{ 
public: 
    Character(void); 
    ~Character(void); 

    Character* creatCharacter(int choice, std::string CharacterName); 

    virtual void Skill_Cast() {}; 
}; 

// Character.cpp 
#include "Warrior.h" 
#include "Archer.h" 

Character* Character::creatCharacter(int choice, std::string CharacterName) 
{ 
    if (choice == 1) 
     return (Character*)new Warrior(CharacterName); 

    if (choice == 2) 
     return (Character*)new Archer(CharacterName); 

    return NULL; 
} 

我還沒有爲你做所有的工作,但這應該指向你正確的方向。

0

如果您使用抽象工廠(很少有用),請做對。你不應該有你的createChracater(在Character類中定義 - 基類不應該知道它的後代)。相反,你應該有一個單獨的文件,有獨立的功能,如下列:

CharacterFactory.h

#include <character.h> 
#include <memory> 
std::unique_ptr<Character> make_character(int type, std::string name); 

CharacterFactory.cpp

#include <warrior.h> 
#include <archer.h> 
#include <stdexcept> 

std::unique_ptr<Character> make_character(int type, std::string name) { 
    if (type == 1) 
     return std::unique_ptr<Character>(new Archer(name)); 
    if (type == 2) 
     return std::unique_ptr<Character>(new Warrior(name)); 
    throw std::runtime_error("Unknown character type requested!"); 
} 
0

在這個片段中......你不用(並且不應該)將派生實例拋回到基類:

Character* creatCharacter(int choice, string CharacterName) 
{ 
    if (choice == 1) 
     return (Character*)new Warrior(CharacterName); 

    if (choice == 2) 
     return (Character*)new Archer(CharacterName); 
    return NULL; 
} 

對於polymorphi sm工作,你的派生類必須繼承基礎。它看起來像你的基類是「Character」,所以這段代碼應該更像下面的代碼。這個想法是,戰士是一個角色(因爲弓箭手是一個角色),所以你不需要(不應該)施放。

Character* creatCharacter(int choice, string CharacterName) 
{ 
    if (choice == 1) 
     return (new Warrior(CharacterName)); 

    if (choice == 2) 
     return (new Archer(CharacterName)); 

    return NULL; 
} 

使用時,只需調用您希望的角色操作即可。或者,更典型地

Warrior warrior; 
warrior.action1(); // because warrior "is-a" 'Character'. 

,從一個指針:

例如,假設字符具有所述方法

virtual void Character::action1(){ ... do stuff }; // body in .cc file 

然後,戰士實例,則可以調用動作1(),如在一個字符數組中。

std::vector<Character*> actionFigures; 

for (<< maybe all figures in vector >>) 
    actionFigures[i]->action1(); 

上面調用字符::動作1()如果派生實例不更換方法。

如果Warrior重新定義了action1(),那麼它的action1()方法的版本將被調用。


還有你已經開始下降的另一個稍大(雖然很常見的)錯誤:多態性的一點是,基類不(不得,也無法)知道可能從它的。派生類以後可能會添加許多代碼版本,可能對基類沒有任何更改。 (即代碼複用)

此功能在意義上的「壞」,對於每一個新的衍生特徵,你將不得不修改這個功能,重新測試一切等(不代碼複用)


這只是額外的指導,而不是爲您編寫代碼。


祝你好運。