是否可以引用随机类?

时间:2013-10-16 00:17:21

标签: c++ class pointers reference

有没有办法让用户输入引用随机类实例?我的意思是基于已创建的?有点像开关,但没有写出开关内的每个实例?我希望我的代码更具通用性,以便其他人可以在不更改开关或代码的其他部分的情况下添加代码。

我知道这个帖子的组织有点锯齿,但我觉得这是组织我对帖子的想法的最佳方式,所以请耐心等待。在最底层的代码中,我创建了一个指针,用于更改“test1”实例中的变量。我希望能够让程序能够获得用户输入以选择哪个类然后在那里更改它。我知道这种语法不起作用,例如:

class test {
public:
    int number;
    int letter;
}
test classTest; //to get user input of which class he wants to select
                //to change a variable
cin >> classTest; //user inputs choice
test * classPointer; //pointer to variables
cin >> classPointer -> number;
cin >> classPointer -> letter;
//where classTest is actually not a normal instance, just a way to get user
//input to select which class instance variables he'd like to change

以下是我的问题开始的一个小背景,这个问题源于此。如果你不关心/需要它来回答我,你可以跳过它。我正在编写一个RPG游戏来练习我用C ++学习的东西,我想让我编写的代码相当普遍。例如,如果我有一个类创建某些在“城镇”中具有通用性的对象。像物品商店,旅馆等。在战斗系统中,您可以选择使用物品。在该项目类别中,应该只列出可用的项目。这没问题,我可以写出大量的if和switch和booleans - 但是我不想为战斗系统中的每个项目写下所有这些我希望某种机制能够为我做到这一点。我相信可以调用指针的一些技巧将是我的问题的补救措施。但是,所有这一切都说请不要被我的背景故事所牵制。它只是为了帮助你看到我的思考过程,如果它不能解决这个问题,那么无论如何我都需要知道这些信息。

#include <iostream>
#include <stdio.h>

class test {
public:
    int number;
    char letter;
    void function() {
        printf("Number = %d\nLetter = %c", number, letter);
    }
    test() {}
    test(int a, char b) : number(a), letter(b) {}
};

int main()
{
    test* pointer;
    test test1(1, 'c');
    pointer = &test1;
    test1.function(); //output initial result
    printf("\nEnter a new number: ");
    std::cin >> pointer -> number; //change number
    printf("Enter a new letter: ");
    std::cin >> pointer -> letter; //change letter
    test1.function(); //output changed result
    return 0;
}

1 个答案:

答案 0 :(得分:1)

我对代码片段和密集文本感到有点迷惑,但你描述的那种问题是一个相当常见的问题。

要根据某些键创建某种类型的对象,您需要将抽象工厂模式作为起点 - 可以在所有优秀的教科书中找到,也可以在您附近有更多信誉良好的wiki。如果它看起来过于夸张,请不要被推迟 - 就像所有图案一样,你可以将它剪下来以满足你的需要。

从本质上讲,对于您想要创建的每种类型的对象,您需要一个知道如何制作它的工厂。制作此相关对象集合所需的所有工厂应共享相同的界面。

要选择正确的工厂来创建所请求的对象类,您需要保存一个键映射,即工厂的字符串。地图取代了您可能想要使用的if-else /开关。如果你想最大限度地减少打字并使你的敌人和朋友混淆,可以使用Singleton来注册工厂,但请首先阅读所有的健康警告:


// Base class for alldwellings in your town
class Dwelling
{
public:
   virtual ~Dwelling() {}
   virtual Dwelling(int number, char letter);
   virtual Enter() = 0;
   virtual Leave() = 0;
   // ... Whatever other common things you can do in a town dwelling */ 
};

// A type of dwelling - as many of these as you like
class Shop : public Dwelling
{
   virtual Shop(int number, char letter)
     : Dwelling (number, letter)
   { /* stuff */}
   virtual Enter();
   virtual Leave();
};

// Base factory class for making a type of dwelling
class AbstractDwellingFactory
{
public:
   virtual DwellingFactory() {}
   virtual Dwelling * Create(int number, char letter) = 0;
};

// Collection and registrar of all dwelling factories - a Meyer's Singleton for convenience
class DwellingFactory
{
public:
   static DwellingFactory & Instance()
   {
       static DwellingFactory theInstance;
       return theInstance;
   }
   // Create a dwelling from the given type and other parameters - consider smart pointers rather than the raw pointer shown here
   Dwelling * Create(std::string const & dwelling dwellingType, int number, char letter)
   {
      // Assuming we have a matching factory, make us a dwelling.
      // Obviously some error checking is required here in the real world 
      return myAbstractDwellingFactoryMap[dwellingType].Create(number, letter);
   }
   void Register(std::strinf const & dwellingType, AbstractDwellingFactory const & fact)
   {
      myAbstractDwellingFactory[dwellingType] = &fact;
   }
private:
   DwellingFactory() {}
   // The actual key to type mapping
   std::map myAbstractDwellingFactoryMap;
};

// A generic concrete factory
template <typename DwellingType>
class ConcreteDwellingFactory : public AbstractDwellingFactory
{
public:
   ConcreteDwellingFactory(std::string const & dwellingType)
   {
      DwellingFactory::Instance().Register(dwellingType, *this);
   }
   // Factory function - note we can return a pointer to a derived type here - look up 'co variant return types'
   DwellingType * Create(int number, char letter)
   {
      return new DwellingType;
   }

};

// A factory instance for each dwelling type you want to support
static ConcreteDwellingFactory<Shop> shopFactory("Shop");

void SomeFunction()
{
   std::string dwellingType;
   int number;
   char letter;

   std::cin >> dwellingType >> number >> letter;
   Dwelling *requestedDwelling(DwellingFactory::Instance().Create(dwellingType, number, letter));
   requestedDwelling->Enter(); // et cetera
}