Participant Question Pointer

$ 4.11 / 2 condition -

A value of type r "for an element B type cv T , where B is a class type, can be converted to a value of r type" a pointer to an element D type cv T , where D is a derived class (Article 10) B If B is inaccessible (item 11), ambiguous (10.2) or virtual (10.1) base class D , a program that requires this conversion is poorly formed.

My question is, why restriction B not a virtual base class D ?

+7
c ++ base-class virtual pointer-to-member
source share
3 answers

Consider the situation associated with a non-virtual base class:

 class A { int a; } class B : public A { int b; } class C : public A { int c; } class D : public B, public C { int d; } 

The memory location is possible here:

 +-------------+ | A: int a; | +-------------+ | B: int b; | +-------------+ | A: int a; | +-------------+ | C: int c; | +-------------+ | D: int d; | +-------------+ 

D ends with two subobjects of A , because it inherits from B and C , and both of them have subobject A

Pointers to member variables are usually implemented as an integer offset from the beginning of the object. In this case, the integer offset for int a in object A is zero. Thus, a "pointer to int a type A " may simply be an integer zero offset.

To convert a "pointer to an int a type A " to a "pointer to an int a type B ", you just need an integer offset in the subobject A located in B (the first subobject A ).

To convert a "pointer to an int a type A " to a "pointer to an int a type C ", you just need an integer offset in subobject A located in C (second subobject A ).

Since the compiler knows where B and C refers to A , the compiler has enough information on how to downcast from A to B or C

Now consider the situation with a virtual base class:

 struct A { int a; } struct B : virtual public A { int b; } struct C : virtual public A { int c; } struct D : public B, public C { int d; } 

Possible memory layout:

 +-------------+ | B: ptr to A | ---+ | int b; | | +-------------+ | | C: ptr to A | ---+ | int c; | | +-------------+ | | D: int d; | | +-------------+ | | A: int a; | <--+ +-------------+ 

Virtual base classes are usually implemented using B and C (which are actually derived from A ) contain a pointer to one subobject A Pointers to subobject A are required because the location of A relative to B and C not constant.

If all that we had was a "pointer to int a type A " we will not be able to attribute it to a "pointer to int a type B " since the locations of subjects B and C can change relative to A A does not have back pointers to B and C , so we just don't have enough information for downcast to work.

+5
source share

With non-virtual inheritance, the members of the base class and the derived class can be laid out contiguously in memory with the base class first, so that each element of the base class is in the same place relative to the address of the object whether the object is B or D This simplifies the conversion of pointer-to-member - <- 20> to pointer-to-member- D ; both can be represented as an offset from the address of the object.

With virtual inheritance, members of the base class must be accessed through a pointer (or equivalent) in the derived object, indicating where the base class is located. This will require the addition of additional information to the member-pointer view to indicate that this indirect action is necessary, and would require checking the runtime when using any member-pointer.

The general principle that underlies most C ++ is to avoid possible overhead at runtime. In this case, the choice was between checking the execution time on a fairly general operation, against rejecting an obscure conversion, and it seems that this principle was applied here.

+1
source share

Really interesting question. Today I learned something new. This is what I could find on the topic: Casting function pointers from a derived class to a virtual base class do not work

0
source share

All Articles