1
votes

I have a base class called Element, a derived class called Vector, and I'm trying to redefine two virtual functions from Element in Vector.

//element.h
template <class T>
class Element
{
public:
Element();

virtual Element& plus(const Element&);
virtual Element& minus(const Element&);
};

and in another file

//Vector.h
#include "Element.h"

template <class T>
class Vector: public Element<T> {
T x, y, z;

public:

//constructors
Vector();
Vector(const T& x, const T& y = 0, const T& z =0);
Vector(const Vector& u);

...

//operations
Element<T>& plus(const Element<T>& v) const;
Element<T>& minus(const Element<T>& v) const;
... 

};

//sum
template <class T>
Element<T>& Vector<T>::plus(const Element<T>& v) const
{
Element<T>* ret = new Vector((x + v.x), (y + v.y), (z + v.z));
return *ret;
}

//difference
template <class T>
Element<T>& Vector<T>::minus(const Element<T>& v) const
{
Vector<T>* ret = new Vector((x - v.x), (y - v.y), (z - v.z));
return *ret;
}

but I always get

error: 'const class Element' has no member named 'x'

So, can I define my virtual functions to take Vector& as an argument instead, or is there a way for me to access the data members of Vector through a pointer to Element?

I'm still fairly new to inheritance polymorphism, fyi.

EDIT: Trying a static_cast (as suggested below) hasn't solved my problem – or I have the wrong syntax for it. I've tried a static cast in the two ways I could imagine, and now my error is > error: 'const class Element' has no member named 'x'

My updated code is: //sum template Element& Vector::plus(const Element& v) const { Element* ret = static_cast*>(operator new((x + v.x), (y + v.y), (z + v.z))); return *ret; }

//difference 
template <class T> 
Element<T>& Vector<T>::minus(const Element<T>& v) const 
{ 
Element<T>* ret = new Vector<T>(static_cast<Vector*>((x - v.x), (y - v.y), (z - v.z)));
return *ret; 
} 

I thought the whole point of inheritance polymorphism is that a reference to a derived class is practically the same as a reference to a base class. Why do I have to jump through these hoops?

2
The word getx does not appear in your code snippet. I think you're missing something. - Stephen
whoops! fixed the code as I was posting - forgot to change the error message. It should be: > error: 'const class Element<double>' has no member named 'x' - Nick Sweet

2 Answers

1
votes

compiler says what is obvious: the base class Element doesn't have member variable 'x' because x is declared and in Vector and not in Element. Try this:

Element<T>& plus(const Element<T>& v) const     {
const Vector<T> & vect = dynamic_cast<const Vector<T> &>(v);
Vector<T>* ret = new Vector((x + vect.x), (y + vect.y), (z + vect.z));
return *ret;
}

Note that If you return a pointer in that manner, you could have any memory leak problem.

1
votes

Can I define my virtual functions to take Vector& as an argument instead

No; the parameter types must be the same in order for the function to override the base class virtual function.

is there a way for me to access the data members of Vector through a pointer to Element?

Yes, but you need to cast the Element& argument to a Vector& using either static_cast or dynamic_cast.

You can only use static_cast if you know for sure that the argument really is a Vector. Of course, if you know this, then you can just change the type of the parameter to be Vector&.

You can use dynamic_cast if you don't know for sure that you actually have a Vector:

const Vector<T>& w = dynamic_cast<const Vector<T>&>(v);

Note that this will succeed if the argument is indeed a Vector and will otherwise fail by throwing std::bad_cast. You can cast pointers instead (dereferencing and taking addresses as appropriate), in which case failures will cause the cast to return null instead of throwing an exception.

That said, inheritance is quite possibly the wrong tool for the job here: it's not entirely clear what your actual use case is for this.