2

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

说,我有一个硬编码的函数:

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

是否可以将控制权转移到某种数据结构中,以便用户只需要填写数据结构来控制函数的行为方式?

4

6 回答 6

2

正如 Neil 在 C++ 中提到的,您不能在运行时发明类。

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

1] 如您的代码片段中所述,您可以使用 switch 或条件语句(对用户提供的数据执行不同的函数)

或者

2]您可以使用工厂模式来创建所需的对象类型(要根据用户提供的数据创建不同的对象,该对象可以有一个通用的基类,可以在代码中替换以生成不同的行为)

或者

3]您可以结合使用a)创建者函数,b)继承和接口c)和动态库加载在运行时创建和加载适当类型的对象。(这是根据给定的用户数据在运行时仅加载特定的对象或函数)

于 2009-07-06T11:13:41.223 回答
1

在 C++ 中,所有类型的名称必须在编译时知道。您不能允许用户在运行时发明类。但是,您发布的功能将起作用 - 配置文件将包含一个整数,指示是否创建 DerivedClass1 或 DerivedClass2。这被读取并用于执行切换。

于 2009-07-06T11:01:01.107 回答
1

您可能会发现工厂方法模式很有用。

于 2009-07-06T11:06:54.653 回答
1

根据问题中提供的有限信息,您可能需要考虑阅读和/或考虑使用 C++ 依赖注入容器。

这可能对您的要求有点沉重,但这很难从问题中看出。仅供参考,依赖注入(http://martinfowler.com/articles/injection.html)是 Martin Fowler 创造的一个术语,是一种更具体的控制反转(我会让你进一步研究这两个主题)。

我个人曾使用 Castle Windsor,它是一个 C#/.NET 依赖注入容器,可以通过配置文件在运行时构造请求的对象。

在 Wikipedia ( http://en.wikipedia.org/wiki/Dependency_injection#Existing_frameworks )上有一个 C++ 依赖注入容器列表——我已经有好几年没有做任何 C++ 了,所以我不能告诉你更多关于它们的信息。

于 2009-07-06T11:57:28.170 回答
1

另一种选择是使用原型模式,其中接口的一部分BaseClassclone()函数。然后你创建一个原型实例数组,并在它们上调用 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
}
于 2009-07-06T12:16:55.567 回答
0

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

于 2009-07-06T11:00:43.183 回答