是否可以控制从配置中创建不同的类?
说,我有一个功能,它执行硬编码:
BaseClass* getClassObject(int type)
{
switch (type)
{
case 1:
return new DerivedClass1();
case 2:
return new DerivedClass2();
default:
return 0;
}
}
是否可以将控件转移到某种数据结构,以便用户只需填写数据结构来控制函数的行为方式?
答案 0 :(得分:2)
正如Neil在C ++中提到的,你不能在运行时发明类。
我可能没有理解你的问题,但是如果你想让一个函数/对象在用户提供的数据上表现不同,你可以根据需要尝试以下任何一个。
1]如您的代码段中所述,您可以使用开关或条件语句(以不同方式对用户提供的数据执行功能)
或
2]您可以使用Factory模式创建所需的对象类型(根据用户提供的数据创建不同的对象,此对象可以在代码中具有可替换的公共基类以生成不同的行为)
或
3]你可以使用组合 a)创作者功能, b)继承和接口 c)和动态库加载 在运行时创建和加载适当类型的对象。 (这是根据给定的用户数据在运行时仅加载特定对象或函数)
答案 1 :(得分:1)
在C ++中,必须在编译时知道所有类型的名称。您不能允许用户在运行时创建类。您发布的函数将起作用 - 配置文件将包含一个整数,指示要创建DerivedClass1或DerivedClass2。这被读取并用于执行切换。
答案 2 :(得分:1)
您可能会觉得有用Factory method pattern。
答案 3 :(得分:1)
根据问题中提供的有限信息,您可能需要考虑阅读和/或考虑使用C ++依赖注入容器。
这可能对您的要求有点重,但这个问题很难说清楚。仅供参考,依赖注入(http://martinfowler.com/articles/injection.html)是Martin Fowler创造的一个术语,是一种更具体的控制反转(我将让您进一步研究这两个主题)。
我个人使用过Castle Windsor,这是一个C#/。NET依赖注入容器,可以通过配置文件运行时构建所请求的对象。
维基百科上有一个C ++依赖注入容器列表(http://en.wikipedia.org/wiki/Dependency_injection#Existing_frameworks) - 自从我做了任何C ++以来已经有几年了,所以我不能告诉你更多关于它们的信息。
答案 4 :(得分:1)
另一种选择是使用原型模式,其中BaseClass
的部分接口是clone()
函数。然后创建一个原型实例数组,并在它们上调用clone来获取新对象。如果要创建值不同的实例以及仅在行为上有所不同的实例,这将非常有用,并且通常比创建工厂方法的工作少一些。
class BaseClass
{
public:
virtual BaseClass* clone () const = 0;
virtual ~BaseClass() { }
virtual void write () const = 0;
};
template <class C>
class Cloneable : public BaseClass
{
public:
virtual BaseClass* clone () const {
return new C ( *static_cast<const C*> ( this ) );
}
};
class TypeA : public Cloneable<TypeA>
{
int value;
public:
TypeA ( int value ) : value ( value ) { }
virtual void write () const {
std::cout << "TypeA ( " << value << " ) @ " << ( void* ) this << std::endl;
}
};
class TypeB : public Cloneable<TypeB>
{
public:
TypeB () { }
virtual void write () const {
std::cout << "TypeB @ " << ( void* ) this << std::endl;
}
};
int main ( int argc, char* argv[] )
{
std::vector<BaseClass*> prototypes;
prototypes.push_back ( new TypeA ( 1 ) );
prototypes.push_back ( new TypeA ( 2 ) );
prototypes.push_back ( new TypeB );
// create some objects
std::vector<BaseClass*> instances;
for ( size_t i ( 0 ); i < 8; ++i )
instances.push_back ( prototypes [ i % 3 ] -> clone() );
for ( size_t i ( 0 ); i < 8; ++i )
instances[ i ] -> write();
// todo: delete everything
}
答案 5 :(得分:0)
我不是C ++大师 - 我来自Delphi / C#背景。在Delphi或C#中,我使用反射来动态创建可能的类列表,然后选择在某个配置文件中配置的类。但是,我不确定这在C ++中是否可行?