How do I get around this? I clearly cannot make the value() method virtual as I won't know what type it is beforehand, and may not know this when accessing the method from b:
class Base
{
public:
Base() { }
virtual ~Base() { }
private:
int m_anotherVariable;
};
template <typename T>
class Derived : public Base
{
public:
Derived(T value) : m_value(value) { }
~Derived() { }
T value() { return m_value; }
void setValue(T value) { m_value = value; }
private:
T m_value;
};
int main()
{
Base* b = new Derived<int>(5);
int v = b->value();
return 0;
}
Compilation errors:
error: 'class Base' has no member named 'value'
This statement:
The variable 'b' is being trated like it is an object of Derived<int>.
So tell the compiler:
Note: If b is not a Derived<int> the result of the cast is NULL.
So the following would probably be safer:
Alternatively by using references you get a bad_cast exception thrown:
Or to be nice and obscrure we can do it one line.
But I think you can achieve what you are trying to do with the boost::any
Some solution:
Another solution:
In this case Base will need to know about the template type so b->value returns a T.
I would suggest adding the template to Base and then make value a virtual function on Base
You could cast your pointer to
Derived
:Of course in real code, you have to add checking to make sure that
dynamic_cast
didn't fail.I think there may be some problems with your design if you ask this question (from my experience, with my designs).
However, there are some workarounds:
But the real question here is what do you try to describe here? What is the meaning of Base, Derived and value(). Ask yourself these question and you may not need these answers...
One way of handling this is via the visitor pattern. The basic idea is that in your hierarchy of classes you implement an
onNode
function that accepts a visitor. Then, you write specific visitors that do what you want. In your case, you'd end up with: