Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何存储一个;“对象类型”;在std::map中?_C++ - Fatal编程技术网

C++ 如何存储一个;“对象类型”;在std::map中?

C++ 如何存储一个;“对象类型”;在std::map中?,c++,C++,长篇介绍,问题在最后: 假设我有一个创建接口的基类 class base { public: virtual ~base(); virtual void calc( int* variables ) = 0; } 还有一些继承的类完成了这项工作(这里只显示了两个): 最后是一些使用这种结构的代码: base* task[2]; task[0] = new add( 0, 1, 2 ); task[1] = new inc( 3 ); int data[4]; /* ... */

长篇介绍,问题在最后:


假设我有一个创建接口的基类

class base
{
public:
  virtual ~base();
  virtual void calc( int* variables ) = 0;
}
还有一些继承的类完成了这项工作(这里只显示了两个):

最后是一些使用这种结构的代码:

base* task[2];
task[0] = new add( 0, 1, 2 );
task[1] = new inc( 3 );
int data[4];

/* ... */

for( int i = 0; i < 2; i++ )
  task[i]->calc( data );
除了变得很难阅读之外,这只是一个线性搜索。因此,本着的精神,我想用
std::map
(或hash-map…)替换线性搜索

经过长时间的介绍,我终于可以回答这个问题了:


如何定义和填充
std::map
,以便以这样一种方式存储对对象的引用(?),即我可以利用该信息在对象上动态创建该引用?

因此,通过上面的代码,我想做一些事情,最终看起来可能是这样的:

// define and fill
std::map< std::sting, ???? > lookup;
lookup["add"] = add;
lookup["inc"] = inc;

/* ... */

// use:
while( linesInConfigAvailable )
{
  /* ... parse ... */
  switch( params.size() )
  {
    case 1:
      task[end] = new lookup[command]( params[0] );
      break;
    case 3:
      task[end] = new lookup[command]( params[0], params[1], params[2] );
      break;
  }
}
//定义和填充
标准::映射<标准::sting,?>查找;
查找[“添加”]=添加;
查找[“inc”]=inc;
/* ... */
//使用:
while(LinesInConfig可用)
{
/*…解析*/
开关(params.size())
{
案例1:
任务[结束]=新查找[命令](参数[0]);
打破
案例3:
任务[结束]=新查找[命令](参数[0],参数[1],参数[2]);
打破
}
}

PS:到目前为止,我的代码中不需要RTTI。如果能保持这样的状态那就太好了…

好吧,你不能。在C++中,类不是对象,它们更像是一个抽象结构,只存在于编译器编译数据时的工作数据中。 但是,您可以使用给定的签名创建所谓的工厂函数:

class A : public Base
{
public:
     static Base* Create() { return new A; }
};

class B : public Base
{
public:
     static Base* Create() { return new B; }
};

...
编辑:如果“创建”函数是这样统一的,您当然可以制作一个模板

然后,您可以在映射中存储函数指针:

typedef Base* (*FactoryType)();
std::map< std::string, FactoryType >

lookup["A"] = A::Create;
lookup["B"] = B::Create;

@Chris为了符合样式指南,您应该以大写字母开头所有类名。例如
base
base
@MartyE这是来自“通用”风格指南吗?(好吧,真实代码中的类名已经以大写字母开头了——但我不确定其余的是否符合要求,而且由于它是OSS,我希望与其他人期望的一样…@MartyE Bullocks。停止传播毫无意义的“建议”@Chris我从谷歌的风格指南中推荐这一建议,尽管它不是通用的。我之所以提到这一点,是因为它在通读时绊倒了我(这是一个类定义,也是类的一个对象)。@MartyE Google的风格指南是谷歌风格的指南。谷歌的风格就是谷歌的风格。它不打算在谷歌之外使用。它不是一份“最佳实践”文件。事实上,它包含了一些与广泛接受的最佳实践背道而驰的观点,因为它们自身的内部组织原因通常不适用于谷歌以外的公司。在
typedef Base*(*FactoryType)(
)中
typedef
做什么?感谢Christian,这就是我一直在寻找的解决方案,我现在正是这么做的(稍微修改以处理构造函数参数)
class A : public Base
{
public:
     static Base* Create() { return new A; }
};

class B : public Base
{
public:
     static Base* Create() { return new B; }
};

...
typedef Base* (*FactoryType)();
std::map< std::string, FactoryType >

lookup["A"] = A::Create;
lookup["B"] = B::Create;
task[end] = lookup[command]();