views:

95

answers:

2

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?

+1  A: 

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.

James McNellis
Thanks, this really helps – I'll be doing a static cast.I'm doing a program for an assignment, and I think the only reason we're supposed to define plus and minus as virtual functions is to get us to explore inheritance. I'd tried to define plus and minus as pure virtual functions, which they should be, but that lead to a catastrophe when I tried to construct a Vector object.Appreciate the help!
Nick Sweet
Actually, this hasn't fully solved my problem. I've tried a static cast in the two ways I could imagine, and now my error is> error: 'const class Element<double>' has no member named 'x'My code is://sumtemplate <class T>Element<T> return *ret;}//differencetemplate <class T>Element<T> return *ret;}
Nick Sweet
@Nick: You need to cast `v` itself, not the result of the expression. I'd recommend getting one of the introductory books from [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)
James McNellis
This works, but it's lead to another issue which I've posted in a separate post*. Thanks!*http://stackoverflow.com/questions/3079980/calling-a-function-from-a-derived-template-class
Nick Sweet
+1  A: 

Hello, 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.

cesare augusto
As above, this works, but it's lead to another issue.And yeah, I realize there's a memory leak, but how do you work around that? I'm using this code for overloading the operator+ as well, and I know you're supposed to return references for those so you can chain operators. Dynamically allocating memory allows me to return a reference, but I'm not quite sure when or how to destroy the created object, or if there's a better way to manage my memory. Any suggestions?
Nick Sweet
There's many ways to delete an object:you can add a destructor method like this: void Vector<T>::destroy() { delete this; } you call this method when you don't need that instance any more.This kind of solution is dangerous because you can call destroy() on a stack allocated object, but works.It would be better if any method that create a new object return the object's pointer instead of its reference.
cesare augusto