【问题标题】:About Polymorphism in C++关于 C++ 中的多态性
【发布时间】:2015-11-04 18:35:12
【问题描述】:

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

#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   

你能解释一下错误并帮我解决这个问题吗,顺便问一下,这是一种“抽象工厂设计模式”吗?非常感谢。 (对不起我的英语不好)

【问题讨论】:

  • 你在声明之前使用的是战士和弓箭手。
  • return (Character*)new Warrior(CharacterName); 没必要,直接说return new Warrior(CharacterName); 还有NhanVat是什么?
  • YourChar-&gt;creatCharacter 行上,您使用的是未初始化的指针。但这并不能解释错误信息。
  • @MohamadElghawi 好吧,classes 已声明,但未定义,因此未声明构造函数。无论如何,这就是问题所在。
  • YourChar = YourChar-&gt;creatCharacter(choice, name); 嗯??您要取消引用未初始化的指针变量?

标签: c++ design-patterns polymorphism


【解决方案1】:

将文件重新排列为头文件/源文件。它会让你的代码更干净、更容易阅读,也能解决你的问题。

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

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

【讨论】:

    【解决方案2】:

    如果您打算使用抽象工厂(这很少用),请正确使用。你不应该有你的 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!");
    }
    

    【讨论】:

      【解决方案3】:

      在这个 sn-p ...中,您不需要(也不应该)将派生实例强制转换回基类:

      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”,所以这段代码应该更像下面这样。这个想法是战士是一个角色(就像弓箭手是一个角色),所以你不需要(不应该)施放。

      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
      

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

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

      或者,更典型的是,来自字符数组中的指针。

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

      上面调用 Character::action1() 只有如果派生实例不替换方法。

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


      还有一个更大(虽然很常见)的错误你已经开始了:多态性的要点是基类不(不应该,不能)知道可能从它派生的东西。派生类可能会在以后添加许多代码版本,而基类可能不会更改。 (即代码重用)

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


      这只是额外的指导,并非试图为您编写代码。


      祝你好运。

      【讨论】:

        猜你喜欢
        • 2014-11-01
        • 1970-01-01
        • 2015-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-05
        • 1970-01-01
        相关资源
        最近更新 更多