reference question

J

junw2000

Hi,

My textbook says that: "Once defined, a reference cannot be reassigned
because it is an alias to its target. What happens when you try to
reassign a reference turns out to be the assignment of a new value to
the target."

I try it using the following code:

#include <iostream>
using namespace std;

struct A {
virtual void f() { cout << "Class A" << endl; }
};

struct B: A {
void f(int) { cout << "Class B" << endl; }
};

struct C: B {
void f() { cout << "Class C" << endl; }
};

int main() {
int i = 10, i1 = 20;
int &ri = i;
ri = i1;
cout << "ri:" <<ri<<" i:"<<i<< endl; //LINE1

B b; C c;
A a;

A* pa1 = &b;

//b.f(); //LINE2
pa1->f(); //LINE3

A &aa = b;
aa.f();

cout << "###REFERENCE####" << endl;
aa = c;
aa.f(); //LINE4
// b.f() //LINE5
}

The output of LINE1 is---ri:20 i:20, so the textbook is correct.

The output of LINE4 is---Class A. And LINE5 can not compile (without
"//"), so b is not assigned the value c. This shows that the textbook
is wrong.

Is the textbook correct only for built-in type?

By the way, LINE2 can not compile due to B::f(int). The output of LINE3
is---Class A, so A::f() is not hiden by B::f(int). Is this due to
dynamic binding?

Thanks a lot.

Jack
 
T

Tom Widmer

Hi,

My textbook says that: "Once defined, a reference cannot be reassigned
because it is an alias to its target. What happens when you try to
reassign a reference turns out to be the assignment of a new value to
the target."

I try it using the following code:

#include <iostream>
using namespace std;

struct A {
virtual void f() { cout << "Class A" << endl; }
};

struct B: A {
void f(int) { cout << "Class B" << endl; }
};

struct C: B {
void f() { cout << "Class C" << endl; }
};

int main() {
int i = 10, i1 = 20;
int &ri = i;
ri = i1;
cout << "ri:" <<ri<<" i:"<<i<< endl; //LINE1

B b; C c;
A a;

A* pa1 = &b;

//b.f(); //LINE2
pa1->f(); //LINE3

A &aa = b;
aa.f();

cout << "###REFERENCE####" << endl;
aa = c;

The above line assigns c to aa, which is a reference to b. The function
to call is statically resolved, so the above is equivalent to:
b.A::eek:perator=(static_cast<A&>(c));
That assigns the A subobject of c to the A subobject of b - this is
called "slicing".
aa.f(); //LINE4

The dynamic type of b cannot be changed by an assignment, and hence that
still calls B::f.
// b.f() //LINE5
}

The output of LINE1 is---ri:20 i:20, so the textbook is correct.

The output of LINE4 is---Class A. And LINE5 can not compile (without
"//"), so b is not assigned the value c. This shows that the textbook
is wrong.

The textbook is correct. Examine this modification of your example to
see what's going on:

#include <iostream>
using namespace std;

struct A {
virtual void f() { cout << "Class A" << endl; }
};

struct B: A {
void f(int) { cout << "Class B" << endl; }
};

struct C: B {
void f() { cout << "Class C" << endl; }
};

int main() {
B b; C c;
A a;

b.A::f();

b.A::eek:perator=(c);

b.A::f(); //LINE4
}
By the way, LINE2 can not compile due to B::f(int). The output of LINE3
is---Class A, so A::f() is not hiden by B::f(int). Is this due to
dynamic binding?

A::f() is hidden by B::f(int), but it is not *overridden* by it.

Tom
 
H

Howard

Hi,

My textbook says that: "Once defined, a reference cannot be reassigned
because it is an alias to its target. What happens when you try to
reassign a reference turns out to be the assignment of a new value to
the target."

I try it using the following code:

#include <iostream>
using namespace std;

struct A {
virtual void f() { cout << "Class A" << endl; }
};

struct B: A {
void f(int) { cout << "Class B" << endl; }
};

struct C: B {
void f() { cout << "Class C" << endl; }
};

int main() {
int i = 10, i1 = 20;
int &ri = i;
ri = i1;
cout << "ri:" <<ri<<" i:"<<i<< endl; //LINE1

B b; C c;
A a;

A* pa1 = &b;

//b.f(); //LINE2
pa1->f(); //LINE3

A &aa = b;
aa.f();

cout << "###REFERENCE####" << endl;
aa = c;
aa.f(); //LINE4
// b.f() //LINE5
}

The output of LINE1 is---ri:20 i:20, so the textbook is correct.

Yes. Both i and i1 now hold the value 20.
The output of LINE4 is---Class A. And LINE5 can not compile (without
"//"), so b is not assigned the value c. This shows that the textbook
is wrong.

Is the textbook correct only for built-in type?

No, but you're trying to call a function. That's not a "value". The
statements contained in functions are not data, and are not copied.

If there were data members in class A, then those data values would be
copied from c to b (which is what aa refers to).

The assignment operator is called, which in the case of references call
either a user-defined assignment operator, or the compiler-generated one in
case you haven't written your own (as in this case). The assignment
operator copies the data from c to b. The _data_, not the functions. (The
functions are not part of individual obejcts of the class, but are common to
the class as a whole).
By the way, LINE2 can not compile due to B::f(int). The output of LINE3
is---Class A, so A::f() is not hiden by B::f(int). Is this due to
dynamic binding?

That's not what 'hiding' means. What did you expect to happen? A compile
error? It can't call B::f(int), because there's no parameter. So what's
left, but to call A::f()? Try removing the (int) parameter.

-Howard
 
H

Howard

Howard said:
The assignment operator is called, which in the case of references call
either a user-defined assignment operator, or the compiler-generated one
in case you haven't written your own (as in this case).

Actually, that's true of any object, not just references. The assignment
operator is called, which by default simply copies the member data.

-Howard
 
J

junw2000

Thanks. I modified my code:

#include <iostream>
using namespace std;

struct A {
virtual void f() { cout << "Class A" << endl; }
};

struct B: A {
int i;
B(): i(111){}
B(int k): i(k){}
void f(int) { cout << "Class B" <<" i: "<<i<< endl; }
};

struct C: B {
int j;
C(): j(100){}
C(int k): j(222), B(k){}
void f() { cout << "Class C" <<" i: "<<i<<" j: "<<j<< endl; }
};

int main() {

B b; C c(333);
A a;

A &aa = b;
A &aa1 = c;
aa1.f();
cout << "###REFERENCE####" << endl;
aa1 = b;
aa1.f(); //LINE1
aa = c;
b.f(i); //LINE2
}

The output of LINE1 is: Class C i: 333 j: 222
This means that c.i is not assigned the value of b.i which is 111.

The output of LINE2 is: Class B i: 111
This means that b.i is not assigned the value of c.i which is 333.

What is the problem?

Thanks.

Jack
 
H

Howard

Thanks. I modified my code:

#include <iostream>
using namespace std;

struct A {
virtual void f() { cout << "Class A" << endl; }
};

struct B: A {
int i;
B(): i(111){}
B(int k): i(k){}
void f(int) { cout << "Class B" <<" i: "<<i<< endl; }
};

struct C: B {
int j;
C(): j(100){}
C(int k): j(222), B(k){}
void f() { cout << "Class C" <<" i: "<<i<<" j: "<<j<< endl; }
};

int main() {

B b; C c(333);
A a;

A &aa = b;
A &aa1 = c;
aa1.f();
cout << "###REFERENCE####" << endl;
aa1 = b;
aa1.f(); //LINE1
aa = c;
b.f(i); //LINE2
}

The output of LINE1 is: Class C i: 333 j: 222
This means that c.i is not assigned the value of b.i which is 111.

The output of LINE2 is: Class B i: 111
This means that b.i is not assigned the value of c.i which is 333.

What is the problem?

The problem is that you're using a reference to an A class object, but
expecting something to happen with data for a B class object. As I said
before, if you have data in the A class, then it will be copied via the
assignment operator for A.

What are you trying to accomplish with all this??? You're making things so
complicated, it's hard to see any purpose. Simpify it. Stop hiding A::f()
with B::f(int), and simply override the virtual function in B and C. Then,
move the data into A. Then try it.

Or just accept what I told you, and what the book told you, which is that
using an assignment operator on a reference causes the assignment operator
for the class (A) to be called, which by default simply copies the contents
[data] from the right-hand-side object to the object the reference refers
to. Simple as that.

-Howard
 
J

junw2000

Thanks.
The problem is that you're using a reference to an A class object, but
expecting something to happen with data for a B class object. As I said
before, if you have data in the A class, then it will be copied via the
assignment operator for A.

What are you trying to accomplish with all this??? You're making things so
complicated, it's hard to see any purpose. Simpify it. Stop hiding A::f()
with B::f(int), and simply override the virtual function in B and C. Then,
move the data into A. Then try it.

Or just accept what I told you, and what the book told you, which is that
using an assignment operator on a reference causes the assignment operator
for the class (A) to be called, which by default simply copies the contents
[data] from the right-hand-side object to the object the reference refers
to. Simple as that.

I am trying to learn reference.
After the line: A &aa = b; is executed, what happens?

Does aa become an alias of b? If so, aa should have all the data
members of b.
But when I write: aa.i = 10000; it can not compile.

Or does aa simply slice the subject of A from b?

Thanks.

Jack
 
V

Victor Bazarov

Thanks.
The problem is that you're using a reference to an A class object,
but expecting something to happen with data for a B class object.
As I said before, if you have data in the A class, then it will be
copied via the assignment operator for A.

What are you trying to accomplish with all this??? You're making
things so complicated, it's hard to see any purpose. Simpify it.
Stop hiding A::f() with B::f(int), and simply override the virtual
function in B and C. Then, move the data into A. Then try it.

Or just accept what I told you, and what the book told you, which is
that using an assignment operator on a reference causes the
assignment operator for the class (A) to be called, which by default
simply copies the contents [data] from the right-hand-side object to
the object the reference refers to. Simple as that.

I am trying to learn reference.
After the line: A &aa = b; is executed, what happens?

If 'b' is of type 'A', then 'aa' is an alias of 'b'. If 'b' is of
a type that has 'A' as a base class, then 'aa' becomes an alias for
the 'A' part of 'b'.
Does aa become an alias of b? If so, aa should have all the data
members of b.

Yes, if.
But when I write: aa.i = 10000; it can not compile.

Or does aa simply slice the subject of A from b?

No, it doesn't slice anything. If 'b' has an 'A' subobject and it is
accessible in the scope of 'aa', then 'aa' becomes an alias for the
'A' part of 'b', which means it has no idea about any portions of 'b'
that are not also part of its 'A' subobject.

V
 
J

junw2000

Victor said:
Thanks.
The problem is that you're using a reference to an A class object,
but expecting something to happen with data for a B class object.
As I said before, if you have data in the A class, then it will be
copied via the assignment operator for A.

What are you trying to accomplish with all this??? You're making
things so complicated, it's hard to see any purpose. Simpify it.
Stop hiding A::f() with B::f(int), and simply override the virtual
function in B and C. Then, move the data into A. Then try it.

Or just accept what I told you, and what the book told you, which is
that using an assignment operator on a reference causes the
assignment operator for the class (A) to be called, which by default
simply copies the contents [data] from the right-hand-side object to
the object the reference refers to. Simple as that.

I am trying to learn reference.
After the line: A &aa = b; is executed, what happens?

If 'b' is of type 'A', then 'aa' is an alias of 'b'. If 'b' is of
a type that has 'A' as a base class, then 'aa' becomes an alias for
the 'A' part of 'b'.
Does aa become an alias of b? If so, aa should have all the data
members of b.

Yes, if.
But when I write: aa.i = 10000; it can not compile.

Or does aa simply slice the subject of A from b?

No, it doesn't slice anything. If 'b' has an 'A' subobject and it is
accessible in the scope of 'aa', then 'aa' becomes an alias for the
'A' part of 'b', which means it has no idea about any portions of 'b'
that are not also part of its 'A' subobject.

V

Thanks a lot. I understand it now!

Jack
 

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

Similar Threads

Tic Tac Toe Game 2
Exception question 1
Reference is not an object. 4
Interaction of delete and destructor 5
Virtual function 2
exception question 10
Reference to class question 1
reference lifetimes... 13

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,191
Latest member
BuyKetoBeez

Latest Threads

Top