2009-07-06 49 views
2

是否有可能控制从配置中创建不同的类?是否可以创建可通过配置控制的不同类?

说,我有一个函数,这是否是硬编码:

BaseClass* getClassObject(int type) 
{ 
    switch (type) 
    { 
    case 1: 
     return new DerivedClass1(); 
    case 2: 
     return new DerivedClass2(); 
    default: 
     return 0; 
    } 
} 

是否有可能控制转移到某些类型的数据结构,使得用户只需要填写数据结构来控制函数的行为?

+1

也许你可以澄清一点问题。你的switch语句有什么问题?在编译时需要知道类型的事实?你想传递一个不同于整数的东西吗(比如说一个带类名的字符串)? – 2009-07-06 11:04:13

回答

0

我不是C++大师 - 我来自Delphi/C#背景。在Delphi或C#中,我会使用反射来动态创建可能的类的列表,然后选择在某个配置文件中配置的类。但是,我不确定在C++中这是否可行?

+0

C++不支持你正在谈论的那种反射。 – 2009-07-06 11:02:07

+0

好吧,那真是太遗憾了;-)把我的答案从有用的答复列表中删除,然后...... – 2009-07-06 11:12:30

+0

或者,您可以删除它,然后开始标记; – 2009-07-06 11:23:57

1

在C++中,编译时必须知道所有类型的名称。您不能允许用户在运行时发现类。但是,您发布的函数可以工作 - 配置文件将包含一个整数,指示是否要创建DerivedClass1或DerivedClass2。这是读取和用于执行开关。

2

正如Neil在C++中提到的那样,你不能在运行时发现类。

我可能没有正确理解你的问题,但是如果你想让一个函数/对象对用户提供的数据有不同的表现,你可以根据你的需要尝试下面的任何一种。

1]在你的代码中提到片断您可以使用开关或条件语句(为用户提供的数据不同的行为函数)来创建所需的

2]可以使用工厂模式对象类型(以创建不同的对象作为每个用户提供的数据,该对象可以具有一个共同的基类为可更换的代码来生成不同的行为)

3]可以使用梳一个创作者函数 b)继承和接口 c)和动态库加载 在运行时创建并加载适当类型的对象。 (这是在运行时按照给定的用户数据仅加载特定对象或函数)

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++已经有几年了,所以我不能告诉你更多关于它们的信息。

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 
} 
相关问题