基于字符串列表访问C ++类

时间:2010-10-05 14:11:55

标签: c++ dynamic

我希望这在C ++中是可行的。

我有一个从公共基类继承的类列表(Base)。所有这些都将被编译为链接到我的程序的库的一部分。

我可以添加更多来自Base的类,并在我执行此操作后重新编译所有内容。

当我的程序启动时,它将收集所有类的向量(使用我已经实现的一些预处理方法),从Base实现。

我想要做的事(你现在可能已经猜到了)就是根据字符串名称从这些类创建对象。这可能吗?

此致

标记

3 个答案:

答案 0 :(得分:2)

好吧,如果你有一个预处理的所有类的列表,那么你可以创建一个构建对象,它将“知道”每个类,并根据请求构建(通过手动搜索列表)。

答案 1 :(得分:2)

取决于你想要做什么。可能有更好的方法来做你需要做的事,但这是一个过于简单的例子......

#include <string>

using namespace std;

class b1{};

class d1 : public b1{};

class d2 : public b1{};

...

int main(int argc, char* argv[]) {
   string name(argv[1]);

   b1* b;

   if (name == "d1")
      b = new d1;
   else if (name == "d2")
      b = new d2;
}

答案 2 :(得分:0)

当然,但不是你想要的方式。 C ++没有反射,所以你必须自己构建机制:(参见下面的EDIT,它实现了工厂指针的映射)

#include <string>
#include <vector>
#include <memory>
using namespace std;

class Base
{
};

class Dog : public Base
{
};

class Cat : public Base
{
};

int main()
{
    typedef vector<string> strings;
    strings names;
    names.push_back("Dog");
    names.push_back("Cat");
    names.push_back("Dog");
    names.push_back("Cat");

    typedef vector<Base*> Bases;
    Bases my_objs;

    for( strings::const_iterator it = names.begin(), it_end = names.end(); it != it_end; ++it )
    {
        if( *it == "Dog" )
            my_objs.push_back(new Dog);
        else if( *it == "Cat" )
            my_objs.push_back(new Cat);

    }
}

编辑:

你在C ++中提出的任何解决方案都将从根本上改变上述内容。一种常见的变体是尝试通过执行某种查找来摆脱if块。这可以使用map对象来实现,该对象将对象的名称链接到实例化它的函数。关于这种方法需要注意的一点是,地图中的函数指针必须具有相同的签名,这意味着DogCat工厂方法必须采用相同数量和类型的参数。这是一个可以使用Boost::Anylink)或其他英雄方法解决的问题,但这超出了本文的范围。

这是一个实现map工厂方法指针的解决方案:

#include <string>
#include <vector>
#include <map>
using namespace std;

class Base
{
public:
    virtual ~Base()  {};
};

class Dog : public Base
{
public:
    static Base* make_dog() { return new Dog; }

};

class Cat : public Base
{
public:
    static Base* make_cat() { return new Cat; }
};

typedef Base*(*ObjFactoryFn)();
typedef map<string, ObjFactoryFn> Factories;


int main()
{
    // set up the map of object factory pointers
    Factories factories;
    factories["Dog"] = &Dog::make_dog;
    factories["Cat"] = &Cat::make_cat;

    // build list of objects we want
    typedef vector<string> strings;
    strings names;
    names.push_back("Dog");
    names.push_back("Cat");
    names.push_back("Dog");
    names.push_back("Cat");

    // build objects using the factory map
    for( strings::const_iterator it = names.begin(), it_end = names.end(); it != it_end; ++it )
    {
        // construct
        Base* my_obj = factories[*it]();    // this should use map's "find" method for robustness
        // destroy
        delete my_obj;
    }

}