Reference assignment through base class reference

S

siddhu

Dear experts,


#include <stdio.h>

class Base
{
};
class Der1:public Base
{
};
class Der2:public Base
{
};

int main()
{
Der1 d1;Der2 d2;
Base& b1 = d1;
Base& b2 = d2;
b1 = b2;
}

Above code gets compiled. But I wonder what does the assignment b1 =
b2; do?If these are pointers then its understandable. But how does
above assignment behave in case of references. Does it exhibit UB?

Regards,
Siddharth
 
G

Gianni Mariani

siddhu said:
Dear experts,


#include <stdio.h>

class Base
{
};
class Der1:public Base
{
};
class Der2:public Base
{
};

int main()
{
Der1 d1;Der2 d2;
Base& b1 = d1;
Base& b2 = d2;
b1 = b2;
}

Above code gets compiled. But I wonder what does the assignment b1 =
b2; do?If these are pointers then its understandable. But how does
above assignment behave in case of references. Does it exhibit UB?

No UB here. Your class might not expect it though. It is commonly
referred to as "slicing". It's also usually not something that is
expected to happen in the implementation and so things can co awry.

It can be prevented by making the base class constructor "protected".
 
V

Victor Bazarov

siddhu said:
#include <stdio.h>
^^^^^^^^^^^^^^^^
What's that for?
class Base
{
};
class Der1:public Base
{
};
class Der2:public Base
{
};

int main()
{
Der1 d1;Der2 d2;
Base& b1 = d1;
Base& b2 = d2;
b1 = b2;
}

Above code gets compiled. But I wonder what does the assignment b1 =
b2; do?If these are pointers then its understandable. But how does
above assignment behave in case of references. Does it exhibit UB?

No, no UB. 'Base' subobject of 'd1' gets the same 'Base' value as
the 'Base' subobject of 'd2'.

V
 
V

Victor Bazarov

Gianni said:
No UB here. Your class might not expect it though. It is commonly
referred to as "slicing". It's also usually not something that is
expected to happen in the implementation and so things can co awry.

It can be prevented by making the base class constructor "protected".

Constructor? Not the copy assignment operator? How does slicing get
into copy assigning objects through references, by the way?

V
 
G

Gianni Mariani

Victor Bazarov wrote:
...
Constructor? Not the copy assignment operator? How does slicing get
into copy assigning objects through references, by the way?

My excuse is I'm sick and I'm sticking to it ...
 
B

BobR

Gianni Mariani wrote in message...
Victor Bazarov wrote:
..

My excuse is I'm sick and I'm sticking to it ...

Take two aspirin and call Dr. Dobbs in the morning! <G>
 
J

James Kanze

#include <stdio.h>
class Base
{};
class Der1:public Base
{
};
class Der2:public Base
{
};
int main()
{
Der1 d1;Der2 d2;
Base& b1 = d1;
Base& b2 = d2;
b1 = b2;
}
Above code gets compiled. But I wonder what does the
assignment b1 = b2; do?

Nothing useful. It assigns the Base part of d2 to the Base part
of d1.
If these are pointers then its understandable. But how does
above assignment behave in case of references. Does it exhibit UB?

Not directly. Of course, class invariants are likely broken,
but that's not a language problem---the language specifies a
behavior here.

In general, assignment doesn't work well with polymorphic
objects. Typically, if a class is designed to be used as a
base, it will have a private assignment operator, so that such
code will be illegal.
 
V

Victor Bazarov

James said:
[..]
In general, assignment doesn't work well with polymorphic
objects. Typically, if a class is designed to be used as a
base, it will have a private assignment operator, so that such
code will be illegal.

*Private* assignment operator? Not *protected*? Just trying to
clarify...

Thanks!

V
 
J

James Kanze

James said:
[..]
In general, assignment doesn't work well with polymorphic
objects. Typically, if a class is designed to be used as a
base, it will have a private assignment operator, so that such
code will be illegal.
*Private* assignment operator? Not *protected*? Just trying to
clarify...

Private. Why would you make it protected, if the goal is to ban
it? Alternatively, you could inherit from something like
boost::uncopiable.
 
V

Victor Bazarov

James said:
James said:
[..]
In general, assignment doesn't work well with polymorphic
objects. Typically, if a class is designed to be used as a
base, it will have a private assignment operator, so that such
code will be illegal.
*Private* assignment operator? Not *protected*? Just trying to
clarify...

Private. Why would you make it protected, if the goal is to ban
it? Alternatively, you could inherit from something like
boost::uncopiable.

If a class is designed to be used as a base, and its assignment op
is private, how the hell are you going to copy the derived class
objects? The default copy assignment op cannot be generated, so
a user-defined has to be provided, which will have to forgo copying
of the base part, which means only the derived portion can be made
"the same as the other one", and the base class subobject will have
to stay the way it was created... That's just wrong, it meanst that
if I have

Derived d1(some_params), d2(some_other_params); // different
assert(d1 != d2);
d1 = d2;
assert(d1 == d2); // how is that going to be true if '=='
// compares the base part as well?

So, either _in_general_ comparing objects of derived class should
NOT involve comparing base class subobjects (which is just wrong
*in general*), or there should be a way to assign bass class
subobjects in a derived class copy assignment operator, which
means the copy assignment operator should be probably *protected*
_in_general_ if the class is intended to serve as a base.

V
 
J

James Kanze

James said:
James Kanze wrote:
[..]
In general, assignment doesn't work well with polymorphic
objects. Typically, if a class is designed to be used as a
base, it will have a private assignment operator, so that such
code will be illegal.
*Private* assignment operator? Not *protected*? Just trying to
clarify...
Private. Why would you make it protected, if the goal is to ban
it? Alternatively, you could inherit from something like
boost::uncopiable.
If a class is designed to be used as a base, and its assignment op
is private, how the hell are you going to copy the derived class
objects?

You're not going to assign them. (A protected copy constructor
is sometimes appropriate. Although in most cases, if a class is
designed to be used as a base class, it has no data to be
copied.)
The default copy assignment op cannot be generated, so
a user-defined has to be provided, which will have to forgo copying
of the base part, which means only the derived portion can be made
"the same as the other one", and the base class subobject will have
to stay the way it was created...

No. The derived class doesn't have to do anything. Assignment
is just not part of the contract, and thus not supported.
 
V

Victor Bazarov

James said:
James said:
James Kanze wrote:
[..]
In general, assignment doesn't work well with polymorphic
objects. Typically, if a class is designed to be used as a
base, it will have a private assignment operator, so that such
code will be illegal.
*Private* assignment operator? Not *protected*? Just trying to
clarify...
Private. Why would you make it protected, if the goal is to ban
it? Alternatively, you could inherit from something like
boost::uncopiable.
If a class is designed to be used as a base, and its assignment op
is private, how the hell are you going to copy the derived class
objects?

You're not going to assign them. (A protected copy constructor
is sometimes appropriate. Although in most cases, if a class is
designed to be used as a base class, it has no data to be
copied.)

"In most cases" is no substitute for "in general". In general even
a class designed to be a base class _may_ contain data [to be copied].
So, in my book, *in general* the copy assignment operator cannot be
private, it has to be protected.
No. The derived class doesn't have to do anything. Assignment
is just not part of the contract, and thus not supported.

WHAT contract are you talking about? "Assignable" is a requirement
for an object to be stored in a standard container, for example.

V
 
G

Gianni Mariani

James Kanze wrote:
....
No. The derived class doesn't have to do anything. Assignment
is just not part of the contract, and thus not supported.

Based on the OP code, I think it was clear that he wanted his classes to
support assignment. The OP just wasn't sure what slicing would do. The
proposal to "protect" the base class assignment operator was simply a
suggestion as a way to disallow assignment other than from a derived class.
 

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

Forum statistics

Threads
473,968
Messages
2,570,150
Members
46,696
Latest member
BarbraOLog

Latest Threads

Top