Pergunta

The following code:

#include <stdio.h>
class Parent
{
public:
    virtual void func() {printf("Parent\n");}
};

class Child1 : public Parent
{
    virtual void func() {printf("Child1\n");}
};

class Child2 : public Parent
{
    virtual void func() {printf("Child2\n");}
};

int main(int argc, char* argv[])
{
    Parent & obj = Child1();
    obj.func();
    obj = Child2();
    obj.func();
    return 0;
}

yields the following results:

expected: Child1 Child2.

actual: Child1 Child1. 

(compiled on VS2010)

I guess that the vptr is not changed by the assignment. It there a way to cause it to be re-created (other than using a pointer to Parent and assigning to it using new)?

thanks

Foi útil?

Solução

You're calling the default assignment operator on obj, which is still of type Child1, with an argument of type Child2. The object itself is still of type Child1. You can verify this by implementing operator = on all 3 classes, and inserting a print statement there.

Outras dicas

Parent & obj = Child1();

You create a reference to an object of type Child1. This is like saying

Child1 c1;
Parent& obj = c1;

obj is now just a different name for c1, which is an object of type Child1.

obj = Child2();
obj.func();

Now, this is like saying

c1 = Child2();
c1.func();

so you see, you're still calling func on an object of type Child1.

Two fundamental properties in C++: an object, once created, never changes its type, and a reference, once initialized, always refers to the same object.

What's happening here is that you are calling the compiler supplied non-virtual operator= for Parent, which is almost certainly not what you wanted. More generally, however, assignment and inheritance don't work well together (precisely because you can't change the type of an object); most of the time, when using inheritance, you should ban assignment (by inheriting from boost::noncopyable, for example). It's possible to implement value semantics for a polymorphic class, using the letter/envelope idiom, but it's a heavy solution, and rarely appropriate.

(I might add that your code doesn't compile with a C++ compiler. You're initializing a reference to a non-const with a temporary, which isn't legal C++. Allowing this is a Microsoft extension.)

References cannot be reseated - they refer to the same object for their entire lifetime. If you want something that can change the object it refers to then you need to use a [smart] pointer instead of a reference.

What you're doing here is slicing an instance of Child2 by assigning it to an instance of Child1.

What you are doing should give an error in compilation. You can not assign a temporary variable (created by Child2()) to a reference variable. You have to create an instance before of Child2, and assign that variable to the reverence.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top