我有多个共享一个公共基类的类,如下所示:
class Base {};
class DerivedA : public Base {};
class DerivedB : public Base {};
class DerivedC : public Base {};
Run Code Online (Sandbox Code Playgroud)
现在,我需要知道在运行时(基于输入)实例化这些派生类中的哪一个.例如,如果是输入"DerivedA",我需要创建一个DerivedA对象.输入不一定是字符串,也可以是整数 - 关键是有某种键,我需要一个值来匹配键.
但问题是,如何实例化该类?C++没有像C#或Java那样的内置反射.我发现一个常见的解决方案是使用这样的工厂方法:
Base* create(const std::string& name) {
if(name == "DerivedA") return new DerivedA();
if(name == "DerivedB") return new DerivedB();
if(name == "DerivedC") return new DerivedC();
}
Run Code Online (Sandbox Code Playgroud)
如果只有几个类,这就足够了,但如果有几十个或几百个派生类,那就变得很麻烦并且可能很慢.我可以很容易地自动化地图创建过程来生成一个std::map<std::string, ***>,但我不知道要存储什么作为值.AFAIK,不允许指向构造函数的指针.同样,如果我使用这个地图做工厂,我仍然需要为每种类型编写一个工厂方法,使其比上面的例子更麻烦.
什么是处理这个问题的有效方法,特别是当有很多派生类时?
我有"工厂"设计模式实现的以下代码.
class Pen{
public:
virtual void Draw() = 0;
};
class RedPen : public Pen{
public:
virtual void Draw(){
cout << "Drawing with red pen" << endl;
}
};
class BluePen : public Pen{
public:
virtual void Draw(){
cout << "Drawing with blue pen" << endl;
}
};
auto_ptr<Pen> createPen(const std::string color){
if(color == "red")
return auto_ptr<Pen>(new RedPen);
else if(color == "blue")
return auto_ptr<Pen>(new BluePen);
}
Run Code Online (Sandbox Code Playgroud)
但我听说可以使用"C++模板"以更好的方式完成.任何人都可以帮助它如何完成以及模板方法如何比这更好?
有什么想法吗
在这个问题中,接受的答案使用以下语法:
typedef std::map<std::string, Base*(*)()> map_type;
Run Code Online (Sandbox Code Playgroud)
有人可以解释(*)的意思,我以前从未见过它吗?
有人可以为我解释Base*(*)(),如:
typedef std::map<std::string, Base*(*)()> map_type;
如何从函数中返回它?
我认为它是一个函数指针,返回一个Base*,但这是什么(*).
我在下面的SO帖子中找到了这个有没有办法从持有类名的字符串中实例化对象?
谢谢
我正在我的C++项目中应用Factory设计模式,下面你可以看到我是如何做到的.我尝试通过遵循"反if"活动来改进我的代码,因此想要删除我所拥有的if语句.不知道怎么办呢?
typedef std::map<std::string, Chip*> ChipList;
Chip* ChipFactory::createChip(const std::string& type) {
MCList::iterator existing = Chips.find(type);
if (existing != Chips.end()) {
return (existing->second);
}
if (type == "R500") {
return Chips[type] = new ChipR500();
}
if (type == "PIC32F42") {
return Chips[type] = new ChipPIC32F42();
}
if (type == "34HC22") {
return Chips[type] = new Chip34HC22();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我会想象创建一个以字符串为键的映射,以及构造函数(或创建对象的东西).之后,我可以使用类型(类型是字符串)从地图中获取构造函数并创建我的对象而不使用任何if.(我知道我有点偏执,但我想知道它是否可以完成.)
可能重复:
有没有办法从保存其类名的字符串中实例化对象?
我正在在具有基类一些C++代码中的问题InputFile,和多个派生类的:TxtInputFile,ASCInputFile,等等,其中每一个派生类是一个特定的输入类型.
我希望能够做的是从命令行中取一个变量,然后生成正确的派生类对象来处理指定的文件类型(例如,用户TXT在命令行中指示,因此,我生成一个TXTInputFile对象并在InputFile标签下返回以供在程序的其余部分使用).
我可以使用一串IF/'ELSE`语句来做这个,将用户输入与一堆预定的文件代码进行比较,但是我希望将来能够添加对新文件类型的支持而无需编辑字符串if语句和添加新文件代码等
有没有办法在运行时访问所有派生类的一些编译器生成的表到基类?
或者可能是某种基于传递参数等于动态绑定的多态构造函数?
(例如InputFile(string)...... TXTInputFile(string temp = "TXT"),ASCInputFile(string temp = ASC")......我意识到这是参数默认值的格式,只是试图用我的思路来表明我的目标.)
提前致谢.
背景:我继承了一个大型系统,该系统使用模板来存储有关类的元数据,这可能会影响这个问题中固有的一些假设。
我正在使用一个模板注册系统,该系统部分基于此处找到的答案:是否有办法从包含类名的字符串中实例化对象?. 宏在我的系统中是行不通的,boost(或任何第三方 API)的使用也是如此。
问题:我是否可以根据输入类型是抽象的还是具体的而使模板的行为有所不同?
我正在寻找这样的东西(此处使用的代码直接从链接问题中接受的答案中复制而来):
struct BaseFactory {
typedef std::map<std::string, Base*(*)()> map_type;
static Base * createInstance(std::string const& s) {
map_type::iterator it = getMap()->find(s);
if(it == getMap()->end())
return 0;
return it->second();
}
protected:
static map_type * getMap() {
// never delete'ed. (exist until program termination)
// because we can't guarantee correct destruction order
if(!map) { map = new map_type; }
return map;
}
private:
static map_type * map;
};
template<typename T>
struct DerivedRegister : BaseFactory {
DerivedRegister(std::string const& …Run Code Online (Sandbox Code Playgroud) 我有一个字符串变量,其中包含结构的名称.此结构在头文件中声明.我想基于结构名称的值创建一个结构的对象,该结构名称保存在C++的字符串变量中.
struct myStruct{
int a;
char b;
};
string structName = "myStruct";
// Instantiate a structure variable [like this: "struct myStruct"]
Run Code Online (Sandbox Code Playgroud)
有人可以帮我这个吗?
c++ ×8
templates ×3
c++11 ×1
class ×1
derived ×1
factory ×1
inheritance ×1
polymorphism ×1
stl ×1
structure ×1