我会将数百个课程的问题简化为两个,并尝试解释我的意思:
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的值来实例化对象。我觉得switch-case不是C ++中最好的方式来实现Base
的更多继承者。
编辑:按照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;
答案 0 :(得分:2)
很大程度上取决于具体情况,但最常见 解决方案可能是使用地图的静态实例来实现 工厂功能。如果地图的键类型很小 整数值,如您的示例中所示,“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)();
}
你会注意到静态如何简化声明(和 函数调用指针 - 指针指向 成员函数已成为函数的简单指针。