【问题标题】:Arrays of Multiple Types多种类型的数组
【发布时间】:2018-06-18 03:16:09
【问题描述】:

所以我目前正在这里做一个小暑期项目——一个基于文本的 RPG(我知道——多么原创!)。无论如何,我遇到了一个问题。我想为我的角色创建一个清单类,其中包含指向不同项目的指针数组。问题是这些物品本身将有许多不同的类别类型(武器、任务、杂项等)。所以我想知道是否有一种方法可以制作一个可以在类型之间切换的指针?还是我的想法完全错误?谢谢。 ——西蒙·沃德

【问题讨论】:

  • 您应该实现某种更通用的对象,例如任何“可库存”继承的通用 Inventory_Object。然后使您的数组成为该类型。
  • 打开您的 C++ 书中解释如何使用std::variant 模板的章节,然后开始阅读。

标签: c++ arrays class pointers


【解决方案1】:

继承应该可以很好地解决这个问题。您所要做的就是创建一个基类(父类),例如一种类型(它应该是什么类型的类-武器,任务,杂项)。每个 itemType 类都将从这个父类继承,当你存储所有这些项目时,你将它们与 objectType 作为父类一起存储,然后当你阅读一个项目时,你查看它的类型,将其转换为适当的类输入,然后用它做你需要做的事情。

class parentItem
{
public:
    parentItem(string) : type(string) {};
    string type; //Doesn't have to be a string, could be an enum or anything you want
}

class weapon : public parentItem
{
    weapon() : parentItem("Weapon"){};
    weaponInfo wInfo;
    int damageDeals;
}

当您从库存中访问其中一个时,代码中的其他位置

parentItem item = player.getWeapon() // Just generic code, just grabbing the object
Weapon* sword;
if(parentItem.type = "Weapon")
{
    sword = (Weapon*)item
}
sword->attack(); //or whatever you want to do with it

TLDR: 在每个项目类上使用继承,以便它们都可以被视为一种类型,然后在您需要访问子类的信息时将它们转换为适当的类型

【讨论】:

  • 哦,好的;我想知道这个。因此,如果我创建一个指向父类的指针数组,我可以让这些指针也指向该父类的任何子类吗?
  • 是的,它们仍然是子类的对象,但它们作为父类存储和访问,因此当您需要子类中不属于父类的某些内容时,您可以将其类型转换为合适的类型
【解决方案2】:

如果您的所有项目类都继承自一个共同的祖先(例如Item 类),您将能够拥有Item * 的向量。这也是使用多态性的好时机:

#include <iostream>
#include <vector>

class Item {
public:
  virtual const char *name() const = 0;
  virtual void use() = 0;
};

class Knife : public Item {
public:
  const char *name() const override { return "Knife"; }
  void use() override { std::cout << "Using the knife" << std::endl; }
};

class Laser : public Item {
public:
  const char *name() const override { return "Laser"; }
  void use() override { std::cout << "Using the laser" << std::endl; }
};

int main() {
  std::vector<std::unique_ptr<Item>> v;
  v.emplace_back(std::make_unique<Knife>());
  v.emplace_back(std::make_unique<Laser>());

  for(const std::unique_ptr<Item> &i : v) {
    std::cout << "Name: " << i->name() << std::endl;
    i->use();
  }

  return 0;
}

输出:

$ c++ --std=c++14 m.cpp
Name: Knife
Using the knife
Name: Laser
Using the laser

【讨论】:

    【解决方案3】:

    您可以有一个 classX 类型的数组(或 std::vector),现在从 classX 派生所有可携带项目。另见Vector that can have 3 different data types C++。这是一个极其简化的示例:

    #include <string>
    #include <vector>
    #include <iostream>
    
    class Carryable {
    public:
        virtual std::string info()=0;
    };
    
    class Potion: public Carryable {
    public:
        std::string name;
        int mana;
        std::string info() { return "potion - name["+name+\
           "] mana["+std::to_string(mana) + "]"; };
    };
    
    class Book: public Carryable {
    public:
        std::string title;
        std::string author;
        std::string info() { return "book - title["+title+"] author["+author+"]"; };
    };
    
    main() {
        std::vector<Carryable*> inventory;
        Potion p;
        p.name="Dragon breath";
        p.mana=40;
        inventory.push_back( &p );
        Book b;
        b.title="Wisdom of Chu";
        b.author="Wen Chu";
        inventory.push_back( &b );
        for (int i=0;i<inventory.size();i++) {
            std::cout << "inventory item " << i << ":";
            std::cout << inventory[i]->info() << "\n";
        }
    }
    

    输出:

    don@oysters:~/proj/src$ ./a.out 
    inventory item 0:potion - name[Dragon breath] mana[40]
    inventory item 1:book - title[Wisdom of Chu] author[Wen Chu]
    

    【讨论】:

      【解决方案4】:

      我知道您可以通过使用Object Oriented Programming 作为Kenny Castrodon brightcfillion 的3 个答案来解决您的问题。但是,void pointer 也是一种解决方案。我知道这不是一个好主意,但它也可以解决您的问题,我想为您介绍一下。我的演示代码如下:

      #include<iostream>
      using namespace std;
      //assume you just have 3 item type
      class A
      {
      public:
          void func(){
             cout<<"I am A object\n";
          }
      };
      
      class B
      {
      public:
           void func(){
              cout<<"I am B object\n";
           }
      };
      
      class C
      {
      public:
           void func(){
              cout<<"I am C object\n";
           }
      };
      
      int main()
      {
        //assume that you have 5 items of three types
        void* items[5];
        char type[5];  //if items[i] is A object then type[i] = 'A'
                       //if items[i] is B object then type[i] = 'B'
                       //if items[i] is C object then type[i] = 'C'
         //When you insert item into array, let's mark 'A', 'B', or 'C' for each item
         items[0]=new A, type[0]='A';
         items[1]=new B, type[1]='B';
         items[2]=new C; type[2]='C';
         items[3]=new B, type[3]='B';
         items[4]=new A, type[4]='A';
      
         for(int i=0;i<5;i++) 
         {
           if(type[i]=='A'){
              ((A*)items[i])->func();
           }
           if(type[i]=='B'){
              ((B*)items[i])->func();
           }
           if(type[i]=='C'){
              ((C*)items[i])->func();
           }
         }
         return 0;
      }
      

      输出

      I am A object I am B object I am C object I am B object I am A object

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-24
        • 2011-05-28
        相关资源
        最近更新 更多