Collin Dauphinee
Collin Dauphinee

Reputation: 13993

Resolving an ID to a derived type at runtime

Let's say I have 100 classes derived from Base. Each of these Derived classes has a unique identifier between [0,100), known at compile time.

I have a function that takes an ID and needs to return a newly allocated instance of the derived class with that ID.

Base* CreateDerived(uint32_t id) {
    return new Derived...();
}

It's evidently not a good solution to have a huge switch case for each ID. An example of the best solution I can come up with is provided below, but I feel like there is a way to do this without the overhead introduced by the vtable.

struct RegisteredClass {
    static RegisteredClass* ClassTable[MAX_DERIVED_CLASSES];
    static Base* CreateDerived(int ID) { return ClassTable[ID]->Create(); }

    RegisteredClass(int ID) { ClassTable[ID] = this; }
    virtual Base* Create() = 0;
};

template<typename T, int ID>
struct Register : RegisteredClass {
    Register() : RegisteredClass(ID) { }
    virtual Base* Create() { return new T; }
};

class Derived34 : Base {
    static Register<Derived34, 34> _register;
};

Am I being silly, or is there another approach to this that doesn't require so much space?

Upvotes: 3

Views: 132

Answers (2)

Mark Ransom
Mark Ransom

Reputation: 308382

Here's a situation where the old crusty macro capability can simplify the task and eliminate some errors.

#define CASE(n) case n: return new Derived##n

Base* CreateDerived(uint32_t id)
{
    switch(id)
    {
        CASE(1);
        CASE(2);
        CASE(3);
        // ...
        default:
            throw std::logic_error("Unhandled Derived## case");
    }
}

#undef CASE

Upvotes: 0

Luchian Grigore
Luchian Grigore

Reputation: 258618

It's evidently not a good solution to have a huge switch case for each ID.

That's actually the abstract factory pattern, and it's widely used just as you described it. I would stick to it, as it's familiar to most programmers.

Your variant seems overly-complicated and hard to maintain.

Upvotes: 1

Related Questions