using template with operator overloading (inheritence)

I've been scratching my head ever since. Please advice if anyone can!
My operator overloading works, but if i use it with templates than it dosent see Class B values. to note: my template works with class A but not B! :(

Class A
{
bool operator<(A pd)
{
return compareLessThan(pd);
}//end of operator< method

bool compareLessThan(A pd)
{
return x>pd.x
}

Class B:public Class A
{
bool compareLessThan(B pd)
{
return (x+y)>(pd.x+pd.y)
}
}

this works if i do not use templates.
but once i implements templates.
the values templates sees are only zero!

template<class T>
bool lessThan(T para1,T para2)
{
return para1<para2;
}//end of lessThan method

Are you sure it's working for the non-templated version?

Function compareLessThan(A pd) needs to be declared virtual, and it needs the same interface in both class A and B. That is, leave the parameter as an A, not a B in both versions.

Then within the version in B, static_cast from an A to a B, and make the comparison.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A
{
  bool operator<(const A& pd)
  {
    return compareLessThan(pd);
  }

  virtual bool compareLessThan (const A& pd)
  {
    return x > pd.x;
  }
};

class B : public A
{
  virtual bool compareLessThan (const A& pd)
  {
    B const& other = static_cast<B const&>(pd);

    return (x + y) > (other.x + other.y);
  }
};


You should also make sure that the static_cast is successful, either by catching any exceptions, or by checking the typeid of the objects.

Cheers,
Jim
First of all, thank you so much for your reply.
yes, im quite sure it works without templates. the templates only work with the base class.
if i use it with the derived class, after much findings, i found out that the templates declares a new object class, in result having all declared to default constructor.
So im curious if there is an extra thing to do with templates for inherited classes.

i did what you said but i got the following error. (NOTE: the given code i gave was a abstract code of my real class, as such naming conventions in error message is diffrent)

//Point2D = class A
//Point3D = class B

Point2D.cpp: In member function ‘virtual bool Point2D::compareLessThan(const Point2D&)’:
Point2D.cpp:78: error: passing ‘const Point2D’ as ‘this’ argument of ‘double Point2D::getScalarValue()’ discards qualifiers
Point3D.cpp: In member function ‘virtual bool Point3D::compareLessThan(const Point2D&)’:
Point3D.cpp:69: error: passing ‘const Point3D’ as ‘this’ argument of ‘double Point2D::getScalarValue()’ discards qualifiers


It would be great if you can enlighten me furthur what does static_cast do?

Last edited on
It looks like you've not changed the body definition of Point3D::compareLessThan() to take a const Point2D& (Point3D.cpp, line 65)

Can't say what's causing the error on line 78 without seeing the code.

static_cast is used to cast one type's pointer or reference to another type's pointer or reference. What the code is doing is converting a Point2D reference into a Point3D reference, so that you can get at the additional members in the Point3D class. You need to do it this way so that all overloaded compareLessThan methods have the same signature (return type and parameter types), so that polymorphism can call the version that matches the object being passed (a Point2D or a Point3D).

Look up static_cast (and related dynamic_cast and typeid) and read up on them.

Cheers,
Jim
thank you for the explanation, i think i kind of understand that now.

So here is the portion of the code that gives me the error

virtual bool Point2D::compareLessThan(const Point2D &pd)
{
bool result = false;
if(distFrOrigin<pd.getScalarValue()) <-----------------Line 78
{
result = true;
}
return result;
}//end of compareMoreThan
Last edited on
Ah yes, I see now.

In changing the compareLessThan parameter to a const reference, we're promising not to change the contents of pd from within the function. The getScalarValue() function isn't declared as const, so it's allowed to change the content - so calling it is going against our promise (even if it doesn't actually change anything).

You can declare getScalarValue() as const by appending the const after the parameter list:

double getScalarValue() const; in the header.

1
2
3
4
double Point2D::getScalarValue() const
{
  // ...
}
in the body.

Unfortunately, it's often the case that adding "const correctness" later in the coding process leads to a lot of code being affected. It's much better to keep it in mind from the outset.

Cheers,
Jim
Thank you for your awesome help so far!

Sorry i am fairly new to c++, const makes the function unalterable right? so are you suggesting that in future, i should make all my get/accessor methods const?

After making changes to the less than, my error still persists.
As i've said previously, i found out that the templates declares a new object class when dealing with derived class, in result having all declared to default constructor.
So im curious if there is an extra thing to do with templates for inherited classes.

anyway this is how i call it.
when i do pd1<pd2, it works.
but when i do a call from the template function. it dosent work.
i did a check, when this getScalarValue()) calls from template.h header file, it returns 0 for class b.
if i did the same below but for class a( base class) it works perfect.

int main()
{
//class b
B pd1(45,43,41);
B pd2(43,43,123);

if(pd1<pd2==true)
{
cout<<"test"<<endl;
}

if(lessThan(pd1,pd2)==true)
{
cout<<pd1.getValue()<<endl;
cout<<"Less than"<<endl;
cout<<pd2.getValue()<<endl;
}
else
{
cout<<"error"<<endl;
}
}
const makes the function unalterable right?

Sort of, yes - when you declare a function as const, what you're saying is that it won't change the value of any class member data (so in our class A/B example, that would be x in class A (and y in class B, too)).

so are you suggesting that in future, i should make all my get/accessor methods const?

It's a good idea, yes - it's safer (and it also allows the compiler to optimise the code much better).

As i've said previously, i found out that the templates declares a new object class when dealing with derived class, in result having all declared to default constructor.


I'm not quite sure what you mean, sorry.

So im curious if there is an extra thing to do with templates for inherited classes.


To make use of the templated version, assuming your definition is

1
2
3
4
5
template<class T>
bool lessThan(T para1, T para2)
{
	return para1 < para2;
}


The following code makes use of it:

1
2
3
4
5
A myA1(12), myA2(20);

if (lessThan<A>(myA1, myA2)) 
  cout << "Less than" << endl;
Thanks for the notes given so far, learn quite abit for the past hour.
hmmm, maybe i can rephrase.
When dealing with base class, my template.h works fine.
When dealing with the derived class, inside template.h, it dosent use the class object that has been inserted into tempate.h.
It creates a new class in result. comparing default values and not the values from the class object being inserted into template.h
which is why i find it very weird. Any idea?

****output when derieved class is used***

DEFAULT DECLARATION //print out when default constructor called.
DEFAULT DECLARATION
Comparing LessThan0 & 0 //print out when template method called
DEFAULT DECLARATION
DEFAULT DECLARATION
Comparing greaterThan0 & 0
DEFAULT DECLARATION
DEFAULT DECLARATION
Comparing equals0 & 0

error

*** output when base class is used ***
Comparing LessThan60.8112 & 60.8112
Comparing greaterThan60.8112 & 60.8112
Comparing equals60.8112 & 60.8112

equals


Try changing the template definition to use T& rather than T on each parameter, then it'll not be making copies of the Point2D/3D objects when using the template class. I suspect your Point2D/3D copy-constructor has an issue of some sort.

Can you post the Point2D class declaration from the header?
hopefully you're still online.

class Point2D
{
public:
//constructor
Point2D();
Point2D(int, int);
Point2D(const Point2D &pd);

//operator overloaded methods
Point2D operator-(Point2D pd);
virtual bool operator<(Point2D pd);
virtual bool operator>(Point2D pd);
bool operator==(Point2D pd);

virtual bool compareMoreThan(const Point2D &pd);
virtual bool compareLessThan(const Point2D &pd);
virtual bool compareEquals(const Point2D &pd);

//accessor,mutator methods
int getX() const;
int getY() const;
virtual double getScalarValue() const;
void setX(int);
void setY(int);

protected:
int x;
int y;
double distFrOrigin;
virtual void setDistFrOrigin();

};
oh great! changing it to & works! omg thank you so much! i would not have thought of it.
thank you soo sooo soo much! :D

oh ya one more thing, when i changed my method to what you said, the following did not work.
other.getX() and other.getY() has no issues as these are basic class methods and they manage to get the values correctly.
other.getZ() has issues getting the value as this is a derived class method. did i do anything wrong?

bool Point3D::compareEquals(const Point2D &pd)
{
Point3D const& other = static_cast<Point3D const&>(pd);
bool result = false;
if(x==other.getX() && y==other.getY() && z==other.getZ()) <---- problem is here
result = true;
return result;
}//end of compareMoreThan
Last edited on
Morning!

Glad you got it working. I can't see anything wrong with your Point3D::compareEquals(), no.
What was the error you got with getZ() ?
hey jim, thanks for the reply, i have already got it working! thanks so much for your help! :D
Topic archived. No new replies allowed.