关于C ++中的多态性

时间:2015-11-04 18:35:13

标签: c++ design-patterns polymorphism

我正在学习多态性,这是一个小游戏。我在这里有一个代表性的角色,我想编程,以便从角色中人们可以选择战士或弓箭手继续游戏。

#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   

顺便说一下,你能解释一下这些错误并帮助我解决这个错误吗?这是一种&#34;抽象工厂设计模式&#34; ?非常感谢。 (抱歉我的英语不好)

3 个答案:

答案 0 :(得分: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;
}

我还没有为你完成所有工作,但这应该指出你正确的方向。

答案 1 :(得分: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!");
}

答案 2 :(得分: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;
}

要使多态性起作用,派生类必须从基类继承。看起来你的基类是“Character”,所以这段代码应该更像下面的代码。这个想法是Warrior是一个角色(因为Archer是一个角色),所以你不需要(不会)施放。

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

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

   return NULL;
}

使用时,只需调用您想要的角色动作即可。

例如,假设Character有方法

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

然后,使用warrior实例,您可以调用action1(),如下所示:

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

或者更典型地,来自Character数组中的指针。

std::vector<Character*>  actionFigures;

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

如果派生实例不替换方法,则上面仅调用Character :: action1()

如果Warrior重新定义了action1(),那么将调用它的action1()方法版本。

还有一个更大(但非常常见)的错误,你已经开始了:多态性的一点是基类不会(不会,不能)知道可能从它派生的东西。派生类可能会在以后添加许多代码版本,可能对基类没有任何更改。 (即代码重复使用)

对于每个新派生的角色,你必须修改这个函数,重新测试一切等等(不是代码重用),这个函数是“破碎的”

这只是额外的指导,而不是为您编写代码。

祝你好运。