#include <iostream>
#include <string>
class A
{
public:
    A(int a) : _a(a) {}
    virtual ~A() {}
    virtual void f() const {std::cout << _a << std::endl;}
private:
    int _a;
};
class B : public A
{
public:
    B(int a, int b) : A(a), _b(b) {}
    virtual void f() const {std::cout << _b << std::endl;}
private:
    int _b;
};
int main()
{
    B b (1,2);
    A a (5);
    A& ref = a;
    ref = b;
    ref.f();
    return 0;
}

Output:

1

I realize that after copying derived (extended) class resist the bottom class object, the derived object has been cut and just the bottom class data replicated. However i believed that the virtual table of 'ref' now ought to be like a virtual table of 'b' so 'ref.f()' should call the function:

void B::f() const {std::cout << _b << std::endl;}

But following the copying the vtbl of 'ref' remains to become the vtbl of sophistication A. why? Thanks.

Virtual table (or, more precisely, pointer towards the virtual table) saved in every polymorphic object isn't replicated.

The reason why behind your "why" real question is not quite obvious. Obviously, it's not replicated. Why if it is replicated? Virtual table is a method to describe the kind-specific behavior of the concrete object. It essentially [not directly] describes the particular kind of the item. Because the actual kind of the item doesn't change throughout copying, the virtual table continues to be same.

First of all 'virtual table' isn't a standard C++ concept. It's a highly implementation specific mechanism to implement dynamic binding and implement virtual functions.

With that said,

However i believed that the virtual table of 'ref' now ought to be like a virtual table of 'b' so 'ref.f()' should call the function

This isn't correct. Virtual table is per class and never per object. It is simply Vptr that's per object.

The kind of 'ref' (as confirmed by typeid(ref).title should you so please) is 'A &'. Whenever you assign 'ref = b' the implicit assigment operator of 'A' is known as with object 'b' because the argument. This operator just blindly copies the 'A' subobject of 'b' in to the current object recommended by 'ref' (that is 'a'). Hence object 'a' presently has the identical condition because the 'A' subobject of 'b'.

As you can tell, within this whole very lengthy story, VTABLE and VPTR doesn't exist whatsoever!.

If you are using pointers (rather than refences), your derived objects stay because they should. Then your vtbl is known as properly.

A* ref;
ref = &b;
ref->f();

Wen you utilize references, the runtime system does not realize that that which you been on ref is really a B. It thinks its an A whenever you perform the assignment.

No, the virtual table doesn't behave as a pointer, and isn't being replicated whenever you assign to some base-class instance (this really is known as slicing).

First, let us clarify your code:

A& ref = a;
ref = b;

Is directly equal to:

a = b;

Now, what goes on here, would be that the A instance's contents are now being changed through the the A area of the B instance's contents. However, it makes sense still an A instance, therefore, it indicates A's virtual table, properly invoking A::f.

A& ref = a; ref = b;

The static in addition to dynamic kind of your reference is A& . Assignment ref = b does not alter the dynamic/static kind of the reference according to your expectation.

From Marshall Cline's C++ FAQ

You cannot separate the reference in the referent.

Unlike a pointer, when a reference is certain to an item, it can not be "reseated" to another object. For the reason that sense, a reference is comparable to a const pointer for example int* const p.

Do this

A& ref = b;  //reference is bound to b [dynamic type of the referent is `B&`]) 
ref.f(); //Prints 2