C ++ virtual inheritance

Source: Internet
Author: User

From: http://www.cppblog.com/chemz/archive/2007/06/12/26135.html

The definition of virtual inheritance and virtual base classes is very simple, and it is very easy to judge whether an inheritance is virtual inheritance. Although the definition of these two concepts is very simple and clear, however, in C ++, virtual inheritance exists as a relatively uncommon but absolutely necessary component, in addition, their behaviors and models both show great differences (including differences in access performance) with General inheritance systems ), now we will thoroughly study the virtual inheritance and virtual base classes in terms of language, model, performance, and application.
First, we should first define virtual inheritance and virtual base classes.

Virtual inheritance: contains the inheritance relationship of virtual keywords in the inheritance definition;
Virtual base class: The base class inherited from virtual in the virtual inheritance system. Note the following:
Class CSubClass: public virtual CBase {}; specifically, CBase is called CSubClass's virtual base class, rather than CBase, which is a virtual base class, because CBase can not be a base class in the virtual inheritance system.

With the above definition, you can start to study the nature of virtual inheritance and virtual base classes. The following describes the syntax, semantics, model, performance, and application.

1. Syntax
The syntax is determined by the definition of the language itself. In general, the syntax is very simple, as follows:
Class CSubClass: public virtual CBaseClass {};

Public, protected, and private inheritance keywords can be modified to ensure that virtual inheritance is included. This forms a virtual inheritance system, at the same time, CBaseClass becomes the virtual base class of CSubClass.

In fact, it is not that simple. What will happen if there is a further inheritance of the virtual inheritance system?

As follows:

/** Base class with data members */class CBaseClass1 {public: CBaseClass1 (size_t I): m_val (I) {} private: size_t m_val ;}; /** virtual inheritance system */class CSubClassV1: public virtual CBaseClass1 {public: CSubClassV1 (size_t I): CBaseClass1 (I) {}}; class CSubClassV2: public virtual cbaslasecs1 {public: round (size_t I): CBaseClass1 (I) {}}; class CDiamondClass1: public CSubClassV1, public CSubClassV2 {public: CDiamondClass1 (size_t I): CBaseClass1 (I ), CSubClassV1 (I), CSubClassV2 (I) {}}; class metadata: public CDiamondClass1 {public: Role (size_t I): CBaseClass1 (I), CDiamondClass1 (I ){}};

Note the content in the constructor initialization list of the CDiamondClass1 and CDiamondSubClass1 classes in the above Code. It can be found that the initialization of the virtual base class CBaseClass1 is included. Without this initialization statement, it will cause a compilation error. Why? Generally, isn't it enough to include initialization in CSubClassV1 and CSubClassV2? To explain this problem, you must understand the semantic features of virtual inheritance. For more information, see the description in the following semantic section.

 

2. Semantics
In terms of semantics, what are virtual inheritance and virtual base classes? The above is just how to write legal virtual inheritance class definitions in the C ++ language. First, let's take a look at the public meaning of the virtual keyword in C ++. In C ++, there are only two places where the virtual keyword can be used, one is the virtual functions of Class Members and the virtual inheritance discussed here. It seems that there is no relationship between the two applications. In fact, they have the common meaning represented by the word virtual in the background semantics, therefore, the same keywords are used in these two scenarios. So what is the meaning of the word "virtual?
Virtual is defined in the traditional American Dictionary [Dual Solution] as follows:
Adj. (adjective)
1. Existing or resulting in essence or effect though not in actual fact, form, or name:
Essentially, what is actually: Although there is no actual fact, form or name, it actually exists or produces results;
2. Existing in the mind, especially as a product of the imagination. Used in literary criticism of text.
Virtual, inner: exists in the mind, especially the product of imagination. Used in literary criticism.

We adopt the first definition, that is, the things or phenomena modified by virtual exist in essence, but they do not have an intuitive representation and cannot be directly described or defined, other indirect methods or means are required to reflect the actual effect.

In C ++, this term is used and cannot be directly called or embodied in the language model. However, it can be called or embodied indirectly. For example, a virtual function must be activated (called) through an indirect Runtime (rather than a compilation) mechanism, virtual inheritance is also a system that can locate access only at runtime. Exist, but indirectly. The key lies in existence, indirect, and sharing.

These three features are well understood for virtual functions. The indirect nature indicates that they must complete function addressing based on the actual objects at runtime, the shared representation shares the virtual functions of the quilt class after the overload in the base class, but actually points to the same function entry.

How do we understand the three features of virtual inheritance? Existence means that the virtual inheritance system and the virtual base class do exist, indirectly, it indicates that when accessing a member of the virtual base class, it must also be done through an indirect mechanism (as described in the model below ), the shared representation is shared in the virtual inheritance system without multiple copies. Now, we can explain the question left behind in the syntax section. "Why should no inheritance class contain the initialization statement of the virtual base class once a virtual base class exists ". The above analysis shows that the virtual base class is shared, that is, no matter how many times it is inherited in the inheritance system, only one sub-object of the virtual base class will appear in the Object Memory Model (this is totally different from multi-inheritance), so that since it is shared, every sub-class will not be exclusive, however, there must always be a class to complete the initialization process of the base class (because all objects must be initialized, even if it is the default one), and the initialization cannot be repeated, who should be responsible for completing initialization? In the C ++ standard (which is also natural), the initialization statement must be written in each inherited subclass (because each inherited subclass may be used to define objects ), the initialization process is actually executed in the lower-level inheritance subclass. Therefore, the initialization statement must be written in each of the above inheritance classes. However, when creating an object, the initialization statement will be executed only in the class constructor used to create the object, other initialization statements are suppressed and not called.

 

3. Model

To implement the three meanings mentioned above, it is natural to consider the object implementation model (that is, the memory model. In C ++, an object is actually a semantic representation of a continuous address space. We will analyze the Memory Model under virtual inheritance.

3.1. exist

That is to say, the object memory must contain the complete sub-objects of the virtual base class, so that the object can be identified through the address. Then, the sub-objects of the virtual base class will be stored in the position (header, middle, and tail) of the object by the compiler. There is no difference. (No matter where the virtual base class is declared in VC8, the sub-objects of the virtual base class will be placed at the end of the Object Memory)

3.2. Indirect

Indirectly, it indicates that a pointer (offset or table) must be included in the direct virtual base bearing subclass to access the virtual base class sub-objects (or members) through the subclass) because the virtual base class sub-objects are shared, there is no definite relationship between them. (In VC8, a virtual base class pointer vbc is placed in the subclass, which points to a slot in the virtual function table. The slot stores the negative offset of the virtual base class sub-object, actually, it is an int type value represented by a complement. When calculating the first address of the virtual base sub-object, you need to add the absolute value of the Offset, this is mainly to be different from the requirement that the virtual function address can only be stored in the virtual table, because the address is a value of the unsigned int type indicated by the original code)

3.3. Share

Sharing indicates that only one sub-object of the virtual base class can be contained in the object's memory space, and the shared reference relationship can be completed through some indirect mechanism. After introducing the complete content, we will attach the test code to reflect the content.

4. Performance

Because of the indirect and shared features, it is determined that objects in the virtual inheritance system will inevitably have a big difference in time and space when accessing objects.

4.1. Time

When an inherited class object is used to access members (including data members and function members) in a virtual base class object, it must be indirectly referenced, this will increase the reference addressing time (just like the virtual function). In fact, it is to adjust the this pointer to point to the virtual base class object, but this adjustment is completed by the running time. (In VC8, you can view * by opening the Assembly output *. the content in the cod file forms three mov indirect addressing statements when accessing the virtual base class Object member, while only one direct addressing Statement of mov constant is used to access the inherited Class Object)

4.2. Space

Because of sharing, different objects store copies of multiple virtual base-class sub-objects in the object memory, which saves space compared with multi-inheritance.

5. Application

After talking about the characteristics and content of multiple languages, under what circumstances should virtual inheritance be used, and how should virtual inheritance be used in general? In fact, it is difficult to answer this question. Generally, if you are sure that there is no need to inherit more, virtual inheritance can be considered when the base class sub-objects must be shared (C ++ standard ios system is like this ). Because each inherited class must contain an initialization statement and only be called in the bottom-layer subclass, in this way, the status of the virtual base class sub-objects obtained by some upper-layer sub-classes may not be as expected (because their initialization statements are suppressed ), therefore, it is generally recommended that you do not include any data member (not stateful) in the virtual base class, but can only be provided as an interface class.

Sample Code:

# Include <iostream> # include <ostream> # include <cstring> using namespace std; class CBase {public: virtual void fun () {cout <"CBase: fun "<endl;} private: char a [3] ;}; class Derived1: public virtual CBase {public: void fun () {cout <" Derived1: fun "<endl ;}}; class Derived2: public virtual CBase {public: void fun () {cout <" Derived2: fun "<endl ;}}; class Derived: public virtual Derived1, public virtual Derived2 // compare the effect of the same virtual to the following {public: void fun () {cout <"Derived: fun "<endl ;}}; class Derived _: public Derived1, public Derived2 {public: void fun () {cout <" Derived _: fun "<endl ;}}; int main () {CBase B; Derived1 d1; Derived2 d2; Derived d; Derived _ d _; cout <"CBase" <sizeof (B) <endl; cout <"Derived1" <sizeof (d1) <endl; cout <"Derived2" <sizeof (d2) <endl; cout <"Derived" <sizeof (d) <endl; cout <"Derived _" <sizeof (d _) <endl; return 0 ;}

Execution result:

 

Because of the indirect pointer introduced by virtual inheritance, the size of the virtual inheritance class is increased by four bytes;

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.