Karl Heinz Buchegger said:
In a nutshell: having op= as virtual is seldome a good idea. Mostly
because it doesn't work how most people would expect it to work.
Hint: polymorphism works only by examining the object the function
is called for, but doesn't take the runtime type of the arguments
into account.
Then programmer must do that, no?
Assume class D, derived from class B
B* p1 = new D;
B* p2 = new D;
*p1 = *p2;
In the above, what do you think the compiler is looking for
when searching a function to fullfil the request of the
assignment? :
1) B:
perator=( const B& Arg );
or 2) B:
perator=( const D& Arg );
or 3) D:
perator=( const B& Arg );
or 4) D:
perator=( const D& Arg );
The symptoms you demonstrate do not exist (nor become better
or worse) because of virtual assignment, but because of how
C++ object model works. In real world, virtual assignment is not
the disease, but the cure!
Consider this example:
// ========================================
struct B
{
// this is a pretty canonical class, except for virtual assignment
virtual B &operator=( const B & );
// virtual destructor needed for derived deletion thru base *
virtual ~B();
// add more members (data or functions) to suit the taste...
};
struct D : public B
{
int value;
D( int i=0 ) : value(i)
{
}
D( const D &r ) : B(r) , value(r.value)
{
}
virtual D &operator=( const D &r )
{
B:
perator=( r );
value = r.value;
return *this;
}
virtual B &operator=( const B &r )
{
const D *p = dynamic_cast<const D *>(&r);
if( p )
{
*this = *p;
}
else
{
// D is being sliced, but now you can detect and compensate!!!
B:
perator=( r );
value = 0;
}
return *this;
}
};
// ========================================
Now your example...
B* p1 = new D;
B* p2 = new D;
*p1 = *p2;
.... will assign as-if using the most intuitive choice...
1) B:
perator=( const B& Arg );
or 2) B:
perator=( const D& Arg );
or 3) D:
perator=( const B& Arg );
or 4) D:
perator=( const D& Arg );
.... which, of course, is 4 .
- Risto -