By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,254 Members | 2,418 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,254 IT Pros & Developers. It's quick & easy.

operator overloading in the derived class could not work...

P: n/a
Hello,

while refreshing my understanding of C++, I found the overloaded
operators could not work properly. Why my following codes keep printing
the student b's data as a person's? Did I lost anything? Thanks for
your help!

person a("John", 30);
student b("Mary", 20, "93406001");
person *p[2] = {&a, &b};
for (int j=0; j<2; j++)
cout << (*p[j]+3) << endl;

The definitions of person and student are listed below.
--------------------------------
class person
{
private:
string name;
int age;
public:
person(string na, int ag):name(na), age(ag) {}
person operator+(int n) const
{
return person(name, age+n);
}
virtual void print(ostream& os) const
{
os << name << " " << age;
}
};

ostream& operator<< (ostream& os, const person &aP)
{
aP.print(os);
return os;
}
-----------------------------------
class student:public person
{
private:
string studentNo;
public:
student(string na, int ag, string sno):person(na, ag), studentNo(sno)
{}
void print(ostream &os) const
{
os << studentNo << " ";
person::print(os);
}
};

Apr 13 '06 #1
Share this Question
Share on Google+
11 Replies


P: n/a
<wf*****@libra.seed.net.tw> schrieb im Newsbeitrag news:11*********************@e56g2000cwe.googlegro ups.com...
Hello,

while refreshing my understanding of C++, I found the overloaded
operators could not work properly. Why my following codes keep printing
the student b's data as a person's? Did I lost anything? Thanks for
your help!

person a("John", 30);
student b("Mary", 20, "93406001");
person *p[2] = {&a, &b};
for (int j=0; j<2; j++)
cout << (*p[j]+3) << endl;

....

What does the program print and what do you expect?

Heinz
Apr 13 '06 #2

P: n/a
Obviously I would like to see the corresponding print function be
issued. Since p[0] refers to a person object, while p[1], a student
object. The result should reasonably be as follows:
John 33
93406001 Mary 23

However, it is quite frustrated. The result it printed out is
John 33
Mary 23

So my question is how to make "the operator+" work as what I want?

Apr 13 '06 #3

P: n/a
<wf*****@libra.seed.net.tw> schrieb im Newsbeitrag news:11**********************@u72g2000cwu.googlegr oups.com...
Obviously I would like to see the corresponding print function be
issued. Since p[0] refers to a person object, while p[1], a student
object. The result should reasonably be as follows:
John 33
93406001 Mary 23

However, it is quite frustrated. The result it printed out is
John 33
Mary 23

So my question is how to make "the operator+" work as what I want?
[Code from original post] person a("John", 30);
student b("Mary", 20, "93406001");
person *p[2] = {&a, &b};
for (int j=0; j<2; j++)
cout << (*p[j]+3) << endl;

The definitions of person and student are listed below.
--------------------------------
class person
{
private:
string name;
int age;
public:
person(string na, int ag):name(na), age(ag) {}
person operator+(int n) const
{
return person(name, age+n);
}


operator+ creates a new object of type person. It doesn't matter that the object for which it has been called is of a derived type. Your code tells the compiler to return a person, not a student, so you get what you asked for. If you want operator+ to behave differently for objects of type student, you have to implement it for class student, too. Without it the compiler does not lnow how to add an int to a student. It only knows that students are persons, too, and how to add an int to a person, and it knows that the result of such an operation is a person, but not a student. Actually, when compiling class person, it doesn't even know that there is such a thing as a student.

HTH
Heinz
Apr 13 '06 #4

P: n/a
Yes. This is a reasonable conjecture, and I tried it before but in
vain. (Sorry for not providing all these information at the very
beginning, 'cause I thought you might ever encounter and solve such
questions.)

I added the following code to the student class, and modified the
access modifier of name and age in person from private to protected,
accordingly.
student operator+(int n) const
{
return student(name, age+n, studentNo);
}

The printed result is still the same.
John 33
Mary 23


Apr 14 '06 #5

P: n/a
- person operator+(int n) const
- {
- return person(name, age+n);
- }

need to be changed into:

+ person & operator+(int n)
+ {
+ age += n;
+ return *this;
+ }

another way:
you can define friend function like
friend person operator+(person &p, int n);

Apr 14 '06 #6

P: n/a
Thanks! Your first method can work. However, it has the drawback of
side-effect: the object's content has been modified. Is there any other
way? The second method, using friend, could not work, even when I
define such a friend function for student class.

Apr 14 '06 #7

P: n/a
> The second method, using friend, could not work, even when I
define such a friend function for student class.


You need a copy constructor. Try it.

Apr 14 '06 #8

P: n/a
Nope, I have tried it, but it still did not work. (Here to work means
it can successfully print out the student object's data; the proposed
friend function can only print out person's data). Should I declare the
operator+ as a virtual function as below? But obviously it won't work
since the derived class could not overwrite it, since their return
types are different. Could someone give me more hints?

class person
{
public:
virtual person operator+(int n) const
{
return person(name, age+n);
}
};

class student: public person
{
public:
virtual student operator+(int n) const
{
return student(name, age+n, studentNo);
}
};

Apr 14 '06 #9

P: n/a
wf*****@libra.seed.net.tw wrote:
Nope, I have tried it, but it still did not work. (Here to work means
it can successfully print out the student object's data; the proposed
friend function can only print out person's data). Should I declare
the operator+ as a virtual function as below? But obviously it won't
work since the derived class could not overwrite it, since their
return types are different. Could someone give me more hints?

class person
{
public:
virtual person operator+(int n) const
{
return person(name, age+n);
}
};

class student: public person
{
public:
virtual student operator+(int n) const
{
return student(name, age+n, studentNo);
}
};


That wouldn't compile. The return value has to be covariant.

I think 'dan2online's suggestion about making your operator + return
a reference has merit.

The main question here is, why do you want to have it as an operator?
Couldn't you use a normal (named) function? The problem, of course,
is that you cannot follow both the recommendation that operator + must
return an object and that virtual functions need to have covariant
returns, _without_ creating some kind of proxy object and building
other things around it. If you just allow your operator+ return
a reference to 'person', your problems should go away.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 14 '06 #10

P: n/a
Tom
Actually, I tried some other solutions, and I guess using += and
clone() might be the best way to avoid this problem.
//---------------------------------------------------------------------------------------
class person
{
protected:
string name;
int age;

public:
person(string na, int ag):name(na), age(ag) {}

virtual person* clone() const
{
return (new person(name, age));
}

virtual person& operator += (int n)
{
age += n;
return *this;
}

virtual void print(ostream& os) const
{
os << name << " " << age;
}
};

ostream& operator<< (ostream& os, const person &aP)
{
aP.print(os);
return os;
}

class student : public person
{
string studentNo;

public:
student(string na, int ag, string sno):person(na, ag),
studentNo(sno)
{}

virtual person* clone() const
{
return (new student(name, age, studentNo));
}

void print(ostream &os) const
{
os << studentNo << " ";
person::print(os);
}
};

int main()
{
student s("student", 20, "1000");
std::auto_ptr<person> sp(s.clone());
std::cout << (*sp += 3) << std::endl;
}

Apr 17 '06 #11

P: n/a
wf*****@libra.seed.net.tw wrote:
Nope, I have tried it, but it still did not work. (Here to work means
it can successfully print out the student object's data; the proposed
friend function can only print out person's data). Should I declare the
operator+ as a virtual function as below? But obviously it won't work
since the derived class could not overwrite it, since their return
types are different. Could someone give me more hints?

class person
{
public:
What you want to do equal to the assignment " person2 = person1 +
age_addition", right ?

So you need (1) default constructor (2) copy constructor (3) friend
function for operatotr +
virtual person operator+(int n) const
{
return person(name, age+n);


person(name, age+n) is live only in the scope of the function inside,
the local object will be deleted when out of the scope. In order to
keep the local object life, you can define it as a static object;

==================================
FYI, you can test the following code:
==================================
#include <iostream>
#include <string>
using namespace std;

class person
{
protected:
string name;
int age;

public:

person() :name(""), age(0){}

person(string na, int ag):name(na), age(ag) {}

person(const person& p);

friend person& operator+(const person&, int n);

virtual void print(ostream& os) const
{
os << name << " " << age;
}

};

person::person(const person& p)
{
name = p.name;
age = p.age;
}

person& operator+ (const person &p, int n)
{
static person default_person;
default_person.name = p.name;
default_person.age = p.age + n;
return default_person;
}

ostream& operator<< (ostream& os, const person &aP)
{
aP.print(os);
return os;

}

int main()
{
person p("student", 20);
cout << p << endl;
cout << p + 5 << endl;
cout << p << endl;
return 0;
}

Apr 17 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.