Multi-Inheritance
An interesting question is as follows:
Struct A {long a, B, c; char d ;}; struct B: public A {long e, f ;};
What is the offset of the above B: e and B: f ing? Different compilers have different ing results, and C ++ does not forcibly define the implementation of derivation. Most compilers set the offset value of B: e ing to 16 (that is, the length of A. For details about the length of custom types, refer to C ++ from scratch (9) ), B: f ing 20. This is equivalent to leaving the space to arrange the member variables of the parent class and then arranging the member variables of the parent class. But there is such a semantics: tomatoes are vegetables and fruits, and whales are marine creatures and preserved animals. That is to say, an instance is both of this type and that type. For this, C ++ provides multiple Derivation or multi-inheritance, and uses "," to separate each parent class, as follows:
Struct A {long A_a, A_ B, c; void ABC () ;}; struct B {long c, B _ B, B _a; void ABC
();};
Struct AB: public A, public B {long AB, c; void ABCD ();};
Void A: ABC () {A_a = A_ B = 10; c = 20 ;}
Void B: ABC () {B _a = B _ B = 20; c = 10 ;}
Void AB: ABCD () {A_a = B _a = 1; A_ B = B _ B = 2; c = A: c = B: c = 3 ;}
Void main () {AB AB; AB. A_a = 3; AB. B _ B = 4; AB. ABC ();}
The above structure AB is derived from structure A and structure B, that is, we can say that AB is an instance of A, B, and AB. How many ing elements will be generated when AB is derived? According to the previous article, apart from the AB: AB and AB: c defined in the AB type definition "{}" (the types are long AB: :), inheritance must also be generated.
To modify the name of each ing element to AB:. The type and value of the ing remain unchanged. Therefore, for two parent classes, eight ing elements are generated (each class has four ing elements). For example, one of them is named AB: A_ B and the type is long: :, the ing value is 4; there is also a name AB: B _ B, the type is long B:, and the ing value is still 4. Note that the names of A: ABC and B: ABC are the same. Therefore, the names of both ing elements are AB: ABC, but the type is void (::)() one is void (B:) (), and The ing addresses are respectively A: ABC and B: ABC. Similarly, the names of the three ing elements are AB: c, and the types are long A:, long B:, and long AB ::, the ing offset values are 8, 0, and 28 in sequence. Sort the member variables of the parent class first and then the member variables of the subclass, so the type is long AB :: the value of c ing is the sum of the length of the two parent classes plus the offset brought by AB: AB. Note: There are two pairs of the above eight ing elements with the same name, but there is no problem because they have different types, in the end, the compiler will modify their names to form symbols based on their respective types, so that there will be no redefinition issues during the connection, but there will be other problems. AB. ABC (); it must be AB. AB: ABC (); short for AB, because AB is AB type, but now there are two AB: ABC, so the above is written directly. ABC will report an error because it cannot know which AB: ABC is required. What should I do?
Looking back at the public, protected, and private inheritance mentioned in the previous article, the public means that the outside world can treat the subclass instance as the parent class instance. That is, all the places where the parent class instance needs to be used. If it is a subclass instance and there is a public inheritance relationship between them, the compiler will perform implicit type conversion to convert the subclass instance to the parent class instance. Therefore, the AB. a_a = 3; actually AB. AB: A_a = 3; while AB: A_a is of the long A: type. The member operators must belong to the same type on both sides. The left type is AB, and AB is A subclass of A. Therefore, the compiler automatically performs implicit type conversion, converts the AB instance to an instance of A, and then computes the member operator.
Note that if the offset values of AB: A_ B and AB: B _ B are 4, AB. A_ B = 3; is it equivalent to AB. B _ B = 3 ;? Even as mentioned above, the AB: A_ B and AB: B _ B types are long A: And long B ::, at most, only the instances converted from the former to the instance and the latter to the B instance. The mappings between AB: A_ B and AB: B _ B remain unchanged. Therefore, the number on the left of the member operator is changed. For structure AB, if the member variables of parent class A are first arranged and then the member variables of parent class B are arranged, then AB :: the offset of B _ B ing should be 16 (the length of structure A plus the offset introduced by B: c), but it is actually mapped to 4, therefore, add 12 (the length of structure A) to the number of the address type on the left of the member operator ). For AB: A_ B, since the member variables of structure A are first arranged, only the offset is 0. Assume that the address corresponding to AB is 3000, for AB. B _ B = 4; the number of the AB type address type is 3000 in ". "on the left, convert it to B type address type number 3012 (because the offset is 12), and then convert". "the number of the Offset type 4 on the Right plus 3012, and then return the number of the address type 3016 of the long type, and continue to calculate" = ". We can also know that the member operator in AB. A_a = 3; finally returns the number 3000 of the long TYPE address type, while AB. A_ B returns 3004, and AB. AB returns 3024.