39
#include <iostream>
using namespace std;

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

template<class T>
class Derived: public Base {
  T _val;
public:
  Derived() {}
  Derived(T val): _val(val) {}
  T raw() {return _val;}
};

int main()
{
  Base * b = new Derived<int>(1);
  Derived<int> * d = b;
  cout << d->raw() << endl;
  return 0;
}

I have some polymorphism problem right now and the code above summarizes everything. I created a Base class pointer and I put the pointer of a new derived template class in it. Then I created a new pointer for the derived template class and I want it to have the reference the base class pointer points to. Even though Base pointer (b) points to a Derived, the reference cannot be passed to Derived class pointer (d) because there's no known conversion from Base * to Derived<int> * (as what the compiler says).

So is there a trick or an alternative way to be able to do it? Thanks in advance.

2

3 Answers 3

65

You must change the base type to be polymorphic:

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

To cast from some supertype to some derived type, you should use dynamic_cast:

Base *b = new Derived<int>(1);
Derived<int> *d = dynamic_cast<Derived<int> *>(b);

Using dynamic_cast here checks that the typecast is possible. If there is no need to do that check (because the cast cannot fail), you can also use static_cast:

Base *b = new Derived<int>(1);
Derived<int> *d = static_cast<Derived<int> *>(b);
Sign up to request clarification or add additional context in comments.

6 Comments

+1 for noticing the Base needs virtual function for dynamic_cast
-1 for saying you "must" use dynamic_cast. You don't have to.
@NeilKirk Correct, but dynamic_cast should be used for that, as it checks whether the cast is possible.
@NeilKirk Visual Studio 2015 will only allow a dynamic_cast, and highlights a static_cast to be an error. +1 returned
@JagsVG they don't need to, unless you want to perform dynamic_cast<> on them
|
6

You can use dynamic_cast

Derived<int> * d = dynamic_cast<Derived<int> *>(b);

If the cast fails (the base pointer does not point to the requested derived type), it returns null.

However, for dynamic_cast to work, your base class must have at least one virtual function. I suggest you make the destructor virtual (this is also prevents other potential problems deleting your objects).

Use of dynamic_cast may indicate bad design in your code.

Note that if you are 100% sure the base pointer, points to your derived type, then you may replace it with static_cast, which is slightly faster. Personally I prefer the extra safety check in general.

Comments

5

Try this:

Derived<int> * d = static_cast<Derived<int>* >(b);

downside it is, that you can cast class that is instance of Base() and then d->raw() will be undefined (segmentation fault likley). If that can be case, use dynamic_cast and have at least one function ob base virtual (having destructors virtual is essential when working with polmorphism).

Virtual functions are under the hood implemented using pointer on virtual table. This pointer can be also used to identify true type of class. This is used by dynamic_cast to check if this conversion can be done and brings small extra overhead when casted.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.