可以基于type_info创建对象吗?

时间:2014-11-04 13:31:43

标签: c++

几乎标题:可以根据type_info创建对象吗?这样做的目的是推迟创建对象。例如,这里是原始"未延期"代码:

Foo* a = new Foo();
Bar* b = new Bar();

这是推迟的:

// Store type indices into a vector
std::vector<std::type_index> types;
types.push_back(std::type_index(typeid(Foo)));
types.push_back(std::type_index(typeid(Bar)));

// Iterate through vector, create objects? Is it possible?

如果这是不可能的,还有其他方式来推迟&#34;物体的构造?

1 个答案:

答案 0 :(得分:7)

在c ++中,没有基于运行时已知类型创建对象的等价物。像C#和Java这样的语言可以准确地实现这一点,因为它们具有广泛的反射支持,而c ++中缺少这种支持。

所有这一切的一个有趣的副作用是c ++开发人员永远无法进入反映一切的诱人领域。由于基于反射的开发非常方便,使用C#和Java构建的企业应用程序中的许多核心功能都围绕着反射。我特别想到的是OR / M软件和库,例如AutoMapper for C#,它们大量使用反射,使用它们的应用程序的整体性能受到严重影响(从个人经验来讲)。在c ++中被禁止使用它实际上令人耳目一新。

好消息是,使用控制架构的双重反转,插件架构非常可行。下面是一个非常简单的例子,展示了一个单独的dll如何使用基本多态来动态注册类型。

#include <string>
#include <list>
#include <unordered_map>
#include <iostream>

// ------------------------------------------------------------
// Host application

class Vehicle
{
public:
    virtual ~Vehicle() {} // Allow proper inheritance
    virtual void Start() = 0; // Start the vehicle
};

class VehicleFactory
{
public:
    virtual ~VehicleFactory() {} // Allow proper inheritance
    virtual Vehicle* Create() = 0;
};

class VehicleTypeFactory
{
public:
    void RegisterFactory(std::string vehicleType, VehicleFactory* vehicleFactory)
    {
        _factories.insert(std::pair<std::string, VehicleFactory*>(vehicleType, vehicleFactory));
    }

    Vehicle* Create(std::string vehicleType)
    {
        return _factories.at(vehicleType)->Create();
    }

    std::list<std::string> GetTypes()
    {
        std::list<std::string> result;
        for(auto& item: _factories)
        {
            result.push_back(item.first);
        }
        return result;
    }

private:
    std::unordered_map<std::string, VehicleFactory*> _factories;
};

class Tractor: public Vehicle
{
public:
    virtual void Start()
    {
        std::cout << "Starting Tractor..." << std::endl;
        std::cout << "Turning on hydraulics..." << std::endl;
    }
};

class TractorFactory: public VehicleFactory
{
public:
    virtual Vehicle* Create()
    {
        return new Tractor();
    }
};


// ------------------------------------------------------------
// Plugin library (.dll, .so)
// plugin introduces brand new type of vehicle
class Limousine: public Vehicle
{
public:
    virtual void Start()
    {
        std::cout << "Starting Limousine..." << std::endl;
        std::cout << "Turning on limo accessories..." << std::endl;
    }
};

class LimousineFactory: public VehicleFactory
{
public:
    virtual Vehicle* Create()
    {
        return new Limousine();
    }
};



// ------------------------------------------------------------
// Host startup: register tractor factory
int main()
{
    VehicleTypeFactory vehicleTypeFactory;
    TractorFactory tractorFactory;
    vehicleTypeFactory.RegisterFactory("tractor", &tractorFactory);

    // ... load plugin(s) which will register other types of factories
    // (
    LimousineFactory limousineFactory;
    vehicleTypeFactory.RegisterFactory("limousine", &limousineFactory);

    // )

    // Now create one of each type of vehicle
    // and tell it to start itself
    for(auto& vehicleType: vehicleTypeFactory.GetTypes())
    {
        auto vehicle = vehicleTypeFactory.Create(vehicleType);
        vehicle->Start();
    }

    return 0;
}

预期产出:

Starting Limousine...
Turning on limo accessories...
Starting Tractor...
Turning on hydraulics...