polymorphism question

C

chresan

Hello,

I have a question about polymorphism in c++. I have much experience in
other programming languages, but not very much in c++. I found an
unexpected behavior in following code

#include <iostream>
using namespace std;

class Abstract
{ public:
virtual void msg()=0;
void printmsg() { msg(); };
};
class A:public Abstract
{ public: virtual void msg() { cout<<"class A"<<endl; }; };
class B:public Abstract
{ public: virtual void msg() { cout<<"class B"<<endl; }; };

int main()
{
A a;
B b;
a.printmsg(); // prints 'class A'
b.printmsg(); // prints 'class B'

Abstract& tmp=a;
tmp.printmsg(); // prints 'class A'
tmp=b;
tmp.printmsg(); // prints 'class A' ???

return 0;
}

Ok, my question is why 'tmp', after 'b' is assigned to it, prints
'class A' instead of 'class B'. But more important: is it possible to
implement the expected behaviour ?

Thank you for any hint. And please excuse if my english is too silly.
Chresan
 
D

David Harmon

On 6 Jul 2005 21:31:21 -0700 in comp.lang.c++, "chresan"
Ok, my question is why 'tmp', after 'b' is assigned to it, prints
'class A' instead of 'class B'. But more important: is it possible to
implement the expected behaviour ?

tmp is a reference. After you create a reference, you CANNOT change
what object it is an alias for. Assigning the value of b to that
object does not change its type.

A pointer instead of a reference would be closer to what you expected.
 
S

Srini

tmp is a reference. After you create a reference, you CANNOT change
what object it is an alias for. Assigning the value of b to that
object does not change its type.

We know that a reference cannot be reseated. But why is reseating a
reference not a compile time error? I tried that snippet with g++ 2.96
with -ansi and -Wall options. It did not give any errors or warning.
Thanks is advance.

Regards,
Srini
 
C

chresan

Yes, I tried it using pointer instead of reference and now it works.
Thank you very much
Chresan
 
D

David White

Srini said:
We know that a reference cannot be reseated. But why is reseating a
reference not a compile time error?

It would be if it were possible to attempt to reseat a reference, but it
isn't. The expression in question merely assigns one object to another, with
the left side being the object to which tmp refers.

DW
 
K

Karl Heinz Buchegger

Srini said:
We know that a reference cannot be reseated. But why is reseating a
reference not a compile time error?

Because there is no syntax for doing it.

What you see as 'reseating' a reference has a very different meaning to the compiler:

A a;
B b;
Abstract& tmp=a;

tmp=b;

You read this as: reseat the reference.
The compiler reads this as: take the value of b and assign it to tmp. Now,
tmp is an alias for a, so the whole thing is equivalent to
a = b;
 
D

David White

Karl Heinz Buchegger said:
Because there is no syntax for doing it.

What you see as 'reseating' a reference has a very different meaning to the compiler:

A a;
B b;
Abstract& tmp=a;

tmp=b;

You read this as: reseat the reference.
The compiler reads this as: take the value of b and assign it to tmp. Now,
tmp is an alias for a, so the whole thing is equivalent to
a = b;

Well, not quite. I nearly said this too, but a = b won't compile because the
reference is to an Abstract and 'a' is type A.

DW
 
J

John Carson

Karl Heinz Buchegger said:
What you see as 'reseating' a reference has a very different meaning
to the compiler:

A a;
B b;
Abstract& tmp=a;

tmp=b;

You read this as: reseat the reference.
The compiler reads this as: take the value of b and assign it to tmp.
Now,
tmp is an alias for a, so the whole thing is equivalent to
a = b;

I am sure you know this, but for the benefit of the OP:

The fact that the reference is to the base class means that what is actually
being assigned is the base component of b to the base component of a. To
make the point clearer, let us consider a Base and Derived class, each of
which has a data member. We consider 4 different objects of the Derived
class.

If you run the following code, you will see that assignment via the Base
reference changes the data member inherited from the Base class, while not
changing the data member from the Derived class. Assignment via a Derived
reference, by contrast, changes the data member from both the Base and the
Derived class, as does direct assignment.

#include <iostream>
using namespace std;


class Base
{
int baseMember;
protected:
Base(int arg) : baseMember(arg)
{}
public:
void PrintMember()
{
cout << "baseMember is " << baseMember << ". ";
};
};

class Derived: public Base
{
int derivedMember;
public:
Derived(int arg) : Base(arg), derivedMember(arg)
{}
void PrintMember()
{
Base::printMember();
cout << "derivedMember is " << derivedMember << endl;
};
};



int main()
{
Derived d1(1), d2(2), d3(3), d4(4);
cout << "After construction:\n";
cout << "d1: ";
d1.PrintMember();
cout << "d2: ";
d2.PrintMember();
cout << "d3: ";
d3.PrintMember();
cout << "d4: ";
d4.PrintMember();


Base& d1_base_alias = d1;
d1_base_alias = d2;
cout << "\nAfter assignment of d2 to d1 via Base reference:\n";
cout << "d1: ";
d1.PrintMember();

Derived& d1_derived_alias = d1;
d1_derived_alias = d3;
cout << "\nAfter assignment of d3 to d1 via Derived reference:\n";
cout << "d1: ";
d1.PrintMember();

d1 = d4;
cout << "\nAfter direct assignment of d4 to d1:\n";
cout << "d1: ";
d1.PrintMember();

return 0;
}
 
U

upashu2

Base& d1_base_alias = d1;it means d1_base_alias is alias of (Base) d1 , not d1. And while
calling d1_base_alias = d2, see d1_base_alias is type of Base, not
derived, so default assingment operator of Base class will be invoked
here. So this line is equivalent to
d1_base_alias = (Base)d2;
So only members of Base class are copied.
And Since d1_base_alias is nothing but (Base)d1, so (Base) d1
datamembers are changed only.
Using pointers, we can reproduce above line as
Base *pBase = &d1;
*pBase = d2; ///See it is not pBase =&d2
d1_derived_alias is nothing but d1, so above lines are same as
d1 = d3.
It will call default assignment operator of derived class, since
d1_derived_alias is of Derived type. so all data memebers (of base &
derived) are copied.
Using pointers we can produce same result as
Derived * pD1 = &d1;
*pD1 = d3;
This line is same as above (d1_derived_alias = d3). So result will be
same.

References are not pointers, they are only aliases.
 
B

benben

just for a matter of interest: the C++ way of referencing objects is
pointers. There was no "reference" in the original C++. Reference was later
added to facilitate operator overloading. :)

ben
 
D

Dan Cernat

benben said:
just for a matter of interest: the C++ way of referencing objects is
pointers. There was no "reference" in the original C++. Reference was later
added to facilitate operator overloading. :)

ben

how did they write copy constructors without references?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,787
Messages
2,569,627
Members
45,329
Latest member
InezZ76898

Latest Threads

Top