我将把我的数百个类的问题简化为两个,并尝试解释我的意思:
class Base {
};
class A: public Base {
};
class B: public Base{
};
static Base* foo (int bar){
switch (bar) {
case 0:
return new A();
break;
case 1:
return new B();
break;
default:
return new Base();
}
}我想根据bar的值来实例化对象。我只是觉得对于更多的Base继承者来说,在C++中切换大小写并不是最好的方式。
编辑:按照我提出的std::map方法:
struct Dictionary {
typedef Base* (Dictionary::*FunctionPointer)(void);
std::map <int, FunctionPointer> fmap;
Dictionary() {
fmap.insert(std::make_pair(0, new A()));
fmap.insert(std::make_pair(1, new B()));
}
Base* Call (const int i){
FunctionPointer fp = NULL;
fp = fmap[i];
if (fp){
return (this->*fp)();
} else {
return new Base();
}
}
};
static Dictionary dictionary;发布于 2013-05-13 17:17:43
这在很大程度上取决于环境,但最常见的解决方案可能是使用映射到工厂函数的静态实例。如果map的键类型是一个小整数值,如您的示例所示,那么"map“只能是一个C样式的数组:
static Base*
foo( int bar )
{
static Base* (*factories[])() = [ &aFactory, &bFactory ];
return bar >= 0 && bar < size( factories )
? (*factories[bar])()
: baseFactory();
}更一般地,您可以使用std::map (用于区分任何可以想象的类型),并且如果不同的键应该产生相同的类型,但具有不同的参数,则可以映射到工厂对象的静态实例,而不是工厂函数。
编辑:
以下是一些改进Dictionary::Call功能的建议:
Base* Dictionary::Call( int i ) const
{
std::map<int, FunctionPointer>::const_iterator
entry = fmap.find( i );
return entry == fmap.end()
? new Base()
: (this->*(entry->second))();
}我使用了const函数,因为它不修改任何东西,而且最重要的是,我使用了std::map<>::find,以避免在映射中插入额外的条目(如果对象不在映射中)。
由于我添加的是const,因此您必须更新typedef:
typedef Base* (Dictionary::*FunctionPointer)() const;另一个建议:除非工厂函数需要访问Dictionary,否则将它们设为静态的。语法要简单得多(而且可能还会提高性能)。static再次更改了typedef:
另外:在构造函数中,new A()不是构造新对象的函数。在C++11中(在lambda和std::function之间)可能有一些东西可以促进这一点,但除此之外,您仍然必须手动编写每个工厂函数。或者,您可以使用模板:
template <typename Target>
Base* construct() const
{
return new Target();
}
Dictionary()
{
fmap.insert( std::make_pair( 0, &Dictionary::construct<A> ) );
// ...
}或者,如果您将它们设为静态:
typedef Base* (*FunctionPointer)();
// ...
template <typename Target>
static Base* construct()
{
return new Target();
}
Base* Dictionary::Call( int i ) const
{
std::map<int, FunctionPointer>::const_iterator
entry = fmap.find( i );
return entry == fmap.end()
? new Base()
: (*entry->second)();
}您将注意到static如何简化声明(以及通过指针调用函数-指向成员函数的指针变成了指向函数的简单指针)。
https://stackoverflow.com/questions/16518065
复制相似问题