Virtual tables when copying objects

#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;
}

Conclusion:

1

I understand that when copying the received (extended) class object to an object of a base class, the derived object is cut and only the data of the base class is copied. But I thought that the virtual table 'ref' should now be like a virtual table 'b', therefore 'ref.f ();' should call the function:

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

But after copying the vtbl 'ref', the vtbl of class A remains. Why? Thank.

+3
source share
6 answers

Firstly, a "virtual table" is not a standard C ++ concept. This is a very implementation-specific mechanism for implementing dynamic binding and implementing virtual functions.

Having said that

, of 'ref' 'b' 'ref.f();'

. - , . Vptr .

'ref' ( typeid (ref).name, ) - 'A &'. 'ref = b', 'A' 'b' . 'A' 'b' , 'ref' ( 'a'). , 'a' , 'A' 'b'.

, VTABLE VPTR !

+3

(, , ), , .

"" . , . ? - . [] . , .

+3

( refences), , . vtbl .

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

, , , ref, - B. , A, .

+2

, ( slicing).

-, :

A& ref = a;
ref = b;

:

a = b;

, , , A A B. - A, A, A::f.

+1

A& ref = a; ref = b;

, A&. ref = b / .

Marshall Cline ++ FAQ

.

, , " " . , const, int* const p.

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

, . , .

A& ref = a;   // Reference
ref = b;

ref a . ref a.

b , ref (, , a).

  • b
  • a -part of b, a ( ref).

After copying, any " b-ness" of the copied object is completely lost along with the previous contents of the object a. The item has _abeen copied, member _band bvtable are torn.

Try this instead:

int main()
{
    B b (1,2);
    A a (5);
    A * ref = &a;  // pointer, not reference
    ref = &b;
    ref->f();
    return 0;
}

This gives a "2" as you probably expected. It also does not overwrite the object a, as the first example did.

0
source

Source: https://habr.com/ru/post/1767767/


All Articles