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

发布于 2024-09-26 12:15:22 字数 251 浏览 1 评论 0原文

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

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

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

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

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

问候

马克

I am hoping this is possible in C++.

I have a list of classes that inherit from a common base class (Base). All of these will be compiled as part of the library linked to my program.

I could be adding more classes that derive from Base and will be recompiling everything after I do this.

When my program starts it will gather a vector of all classes (using some preprocessing method I have already implemented) that implement from Base.

What I want to do (you have probably guessed by now) is to create objects from these classes just based on the string names. Is this possible?

Regards

Mark

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苦妄 2024-10-03 12:15:22

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

Well, if you have a preprocessed list of all classes then you can create a construction object that will "know" each of those classes and will construct (by manually searching through the list) them upon request.

旧时光的容颜 2024-10-03 12:15:22

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

#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;
}

Depends on what you're trying to do. There are probably better ways to do what you need to do but here's an oversimplified example...

#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;
}
江南烟雨〆相思醉 2024-10-03 12:15:22

当然可以,但不是你想要的方式。 C++ 没有反射,因此您必须自己构建该机制:(请参阅下面的编辑,它实现了工厂指针的映射)

#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::Any 解决(link)或其他英雄方法,但这超出了本文的范围。

这是一个实现工厂方法指针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;
    }

}

Sure, but not the way you would like. C++ has no reflection, so you have to build the mechanism yourself: (See below for EDIT which implements a map of factory pointers)

#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);

    }
}

EDIT:

Any solution you come up with in C++ is going to be fundamentally some variation of the above. One common variation is to try to get rid of the if block by doing some kind of lookup. This can be implemented using a map object which links the name of the object to a function that instantiates it. One thing to note about this approach is that the function pointers in the map have to have the same signature, meaning theDog and Cat factory methods have to take the same number and type of parameters. This is a problem that can be solved using Boost::Any (link) or other heroic methods, but that's beyond the scope of this post.

Here's a solution that implements a map of factory method pointers:

#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;
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文