Home > OS >  Is it possible to get derived type from base class without template?
Is it possible to get derived type from base class without template?

Time:12-06

I have referred to many documents here, but I have a question because I cannot get a clear answer.

To help you understand, you have explicitly renamed functions, variables, and classes.

// interface.h
class Base {
    ...
};

class Derived_A : public Base {
    ...
    void foo_A() { return 1; }
};

class Derived_B : public Base {
    ...
    void foo_B() { return 2; }
};

// manager.h && manager.cpp
class Manager
{
    static std::vector<Base*> g_lists;
    // It also proceed below.
    // g_lists.push_back(new Derived_A);
    // g_lists.push_back(new Derived_B);

public:
    // How can I changed this method ?
    static auto getDerived(char _type);
}
...

auto Manager::getDerived(char _type)
{
    auto base = g_lists[get_index_from_type(_type)];

    if (base == nullptr)
        return nullptr;

    if (_type == 'A')
        return (dynamic_cast<Derived_A>(base))
    else if (_type == 'B')
        return (dynamic_cast<Derived_B>(base))
    else
        return nullptr;
}

// main.cpp

int main()
{
    // I want to using like this
    auto ptr = Manager::getDerived('B')
    ptr->foo_B();
}

I already know that it is possible if use the template as below.

template<class Type>
Type* getDerived(char _type)
{
    if (g_lists[idx])
        return dynamic_cast<Type*>(g_lists[idx]);
    else return nullptr;
}

// user side
auto ptr = getDerived<Derived_A>('A');

However, I want to make a code that avoids using class "Derived_" from the user's point of view.

Is there any good way for me?

CodePudding user response:

NO, it's not possible what you are asking, because a function/method can have a single return type, which is decided at compile time.
The most basic way is to return the Base pointer/reference:

static Base* getDerived(char _type);

And whichever method you intend to invoke, should be virtual:

class Base {
  virtual void foo_A ();
  virtual void foo_B ();
};

This way a correct method ptr->foo_B() will be invoked. It will also save you from lot of boilerplate code. Remember that the cost of virtual method is insignificant for the benefits it provide and are meant for such scenario.

Reference from Bjarne Stroustrup's official page:

In my experience, the efficiency reason is usually misplaced fear. In C , virtual function calls are so fast that their real-world use for a class designed with virtual functions does not to produce measurable run-time overheads compared to alternative solutions using ordinary function calls.

CodePudding user response:

No, it's not possible. The returning type auto in your auto Manager::getDerived(...) is actually resolving the return type in compile-time to SOME_TYPE when you do return (dynamic_cast<SOME_TYPE>(base)). So you need a template for your compiler to know what SOME_TYPE is.

CodePudding user response:

if the type is known at compile-time, you can change it to template parameter

template<char type>
auto getDerived()
{
    Base* base = GetAsBase(type);

    if constexpr (type == 'A')
        return static_cast<Derived_A*>(base); // static_cast, it should success afaict
    else if constexpr (type == 'B')
        return static_cast<Derived_B*>(base); 
    else
        return nullptr;
}
int main()
{
    auto ptr = getDerived<'B'>()
    ptr->foo_B();
}
  • Related