Bob
Bob

Reputation: 4980

How to get a reference/pointer to a class (not an object)?

I have a std::map where key is string and I want the value to be, not an object, but a reference/pointer to a class which I can instantiate.

std::map<::std::string, ?class_reference?> handlers_;

Once the specific entry is chosen, I want to create instance of the class and execute a member function.

Upvotes: 0

Views: 124

Answers (2)

user10957435
user10957435

Reputation:

How to get a reference/pointer to a class (not an object)?

Short answer, you can't. Unfortunately, C++ doesn't work that way.

However, to solve your specific problem, you have the option of a factory pattern, which would look something like this:

template <class T>
class factory {
    public:
        virtual std::unique_ptr<T> createObject() = 0;
};

class base { // some base class common to all the types you are intending to create

};

class foo : public base { // some class you want to create

};

class fooCreator : public fatory<base> {
    public:
        std::unique_ptr<T> createObject() {
            return someUniquePointerToANewObject;
        }
}


int main() {
    std::map<std::string, std::unique_ptr<factory<base>>> myMap; // because we are creating some bases

    myMap["some key"] = new myFooCreator;

    // now let's create some new `base`
    if(myMap.find("some matching key") != myMap.end()) {
        std::unique_ptr<base> myBaseObject = myMap["some matching key"]->createObject();

        // use created object
    }

    return 0;
}

Of course, there are a lot of things that could go wrong here, like if for some reason you push a nullptr to myMap. But at least you have an idea of what it looks like now.

Upvotes: 0

SPD
SPD

Reputation: 388

As others have already mentioned, if you want to create relevant objects via a string (such as class name), you'll need to use factory pattern which can create related objects (same base class). Here's a simple example easy to understand (you just store lambda which returns objects in the map):

#include <map>
#include <string>
#include <functional>
#include <iostream>

class Base {};

class A : public Base{
    public:
    A() { std::cout << "A ctr" << std::endl; }
};

class B : public Base {
    public:
    B() { std::cout << "B ctr" << std::endl; }
};

int main() {
    std::map<std::string, std::function<Base*()> > m;
    m["a"] = []() { return new A(); };
    m["b"] = []() { return new B(); };
    m["a"]();
    m["b"]();

}

Upvotes: 1

Related Questions