1. Why should we introduce Virtual inheritance?
Virtual inheritance is a special concept in Multi-inheritance. The virtual base class is designed to solve multiple inheritance issues. For example, Class D inherits from Class B1 and B2, while Class B1 and B2 inherit from Class A. Therefore, the variables and functions in Class A appear twice in Class D. To save memory space, you can define the inheritance of B1 and B2 to AVirtual inheritanceAnd A becomesVirtual base class. The implementation code is as follows:
Class
Class B1: public virtual;
Class B2: public virtual;
Class D: public B1, public B2;
Virtual inheritance is rarely used in general applications, so it is often ignored because in C ++, multi-inheritance is not recommended or commonly used, once multiple inheritance is removed, virtual inheritance completely loses its necessity because it only reduces efficiency and occupies more space.
Because C ++ supports multiple inheritance, duplicate base classes may occur in this case, that is, the possibility of using a class twice as the base class. For example
# Include <iostream> cout <DerivedA: cout <DerivedB: cout <value <};
The compilation errors are as follows:
In this case, compilation errors with unclear paths may occur when accessing value in MyClass. to access data, you need to display and limit it. Change to DerivedA: value or DerivedB: value to eliminate ambiguity. In addition, a public Base class like Base should not be expressed as two separated objects. To solve this problem, the virtual Base class can be used for processing. If virtual inheritance is used, the compilation is normal, and the class structure is as follows.
The feature of virtual inheritance is that the virtual base class in any derived class is always represented by the same (shared) object.As shown in.
2.What is the difference between introducing virtual inheritance and direct inheritance?
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.
2.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.
2.2 space:Because of sharing, it is not necessary to save multiple copies of the virtual base class sub-objects in the object memory, which saves space compared with multi-inheritance. The difference between virtual inheritance and general inheritance is that virtual inheritance can prevent the occurrence of diamond inheritance, when a derived class contains two sub-objects of the base class at the same time. That is to say, in order to ensure this, in the case of virtual inheritance, the layout of base class sub-objects is different from that of General inheritance. Therefore, it requires an Extra pointer to the base class sub-object.
Case 1: Case 2: Case 3: Case 4:
Class
{{{{
Virtual void func ();
};}; Char x;
Class B: publicA class B: public };};
{Class B: public A class B: public
Virtual void foo ();{{
};}; Virtual void foo ();
};};
BecauseEach class with a virtual function must have a 4-byte pointer pointing to its own virtual function table.So there should be no problem with the number of bytes occupied by Class a in each case. How can we calculate the number of bytes of Class B? Looking at the "first" and "third" situations, we use virtual inheritance. At this time, we need to have such a pointer vptr_ B _a, which is called a virtual class pointer and is also four bytes; it also includes the number of bytes of Class a, so the number of bytes of Class B is obtained. The "second" and "fourth" cases do not include the vptr_ B _a pointer. This time, we should have a problem.
b: };
At this point: sizeof (a) = 4, sizeof (B) = 4
b: };
Strangely, sizeof (a) = 4, sizeof (B) = 4. Although virtual is added before voif foo () in class B, the results are the same.
b: };
At this point: sizeof (a) = 4, sizeof (B) =8
b: };
At this time: sizeof (a) =1, Sizeof (B) =4
b: };
At this point: sizeof (a) = 1, sizeof (B) = 1
For example:
B : C : D : A , };
The above answers are 1, 1, 4, and 1 respectively, which indicates:Empty category occupies 1 Space,A single inherited empty class space is also 1,The null class space of multiple inheritance is still 1. However, the size of sizeof (C) is 4
I believe that, after the above analysis and comparison, I will not be confused about such problems in the future, and there will be a feeling of "getting out of the water.
For a more detailed summary of the byte, see: http://www.cnblogs.com/heyonggang/p/3253036.html
Http://www.cnblogs.com/heyonggang/archive/2012/12/11/2812304.html
Now that we have talked about inheritance, we may wish to discuss the frequently-mentioned overload, overwrite, and hide.
(1) the same range (in the same class );
(2) The function name is the same;
(3) parameters are different;
(4) virtual keywords are optional.
(1) different scopes (located in the derived class and the base class respectively );
(2) The function name is the same;
(3) The parameters are the same;
(4) basic functions must have virtual keywords.
(1) If the function of the derived class and the function of the base class have the same name but different parameters, the function of the base class will be hidden regardless of whether there is a virtual keyword (be careful not to confuse the function with the overload ).
(2) If the function of the derived class has the same name as the function of the base class, but the parameter is the same, the base class function does not have the virtual keyword. In this case, the function of the base class is hidden (do not confuse with overwrite ).
To put it bluntly, if the function names and parameters of the derived class and the base class are the same, they are covered. This is understandable. If the function names are the same, the parameters are different, is hidden.
4.4.1 overload: Check the parameters.
4.4.2 hide: Call whatever you use.
4.4.3 overwrite: Call the derived class.
#include <iostream> B: cout<<(A)<< cout<<(B)<< }
At the beginning, I thought that the subclass inherits the private variables of the parent class but does not inherit the parent class, so I think the result is. In fact, the result is. That is to say, the subclass inherits the private variables of the parent class, but it cannot be accessed. For cainiao like me, it cannot be turned around at once. Later, let's take a look at the materials,Otherwise, if only the function is inherited and the variable is not inherited, then the function of the parent class will not become useless. Therefore, all the variables of the parent class must be inherited, so that the variables of the parent class can be protected and the functions of the parent class can be used.
Output The following class size:
[Cpp]View plaincopyprint?
- Class X {};
- Class Y: public virtual X {};
- Class Z: public virtual X {};
- Class A: public Y, public Z {};
Inheritance relationships include:
This is probably because none of them have obvious data, which only indicates the inheritance relationship. But at least I think class x should be 0. He has nothing. The result is unexpected. The size of the test in vs2010 is: (different compilers may have different sizes)
[Cpp]View plaincopyprint?
- Cout <"sizeof X:" <sizeof X <endl
- <"Sizeof Y:" <sizeof Y <endl
- <"Sizeof Z:" <sizeof Z <endl
- <"Sizeof A:" <sizeof A <endl;
It's strange. Why is this result. An empty class is actually not empty. It has a hidden 1 byte, which is a char inserted by the compiler. This ensures that the size of the defined object is unique in the memory, you can test it on your own, for example:
[Cpp]View plaincopyprint?
- X xa, xb;
- If (& xa = & xb)
- Cout <"is equal" <endl;
- Else
- Cout <"not equal" <endl;
But what people do not understand is the size of Y and Z. The main cause is that:
- The extra burden caused by the language itself. When the language supports virtual base classes, it will lead to an extra burden. This is generally a virtual table pointer. It stores the address of the virtual base sub-object, that is, the offset.
- The compiler provides Optimization in special cases because class X has a size of 1 byte, which occurs on class Y and class Z. This depends on the compiler. For example, some compilers ignore this 1byte (because the virtual pointer has been used, this 1byte can not be used as a location in the memory ).
- Alignment is a so-called Alignment operation. For example, if you use a 5 bytes compiler, Alignment is aligned to 8 bytes for more efficient access in the memory.
The following describes the model in vs2010,Because 1byte does not need to be used with a virtual pointer, the size of class Y and class Z is 4 bytes.Such:
What do you think is the size of class? A virtual base class sub-object only has one entity in the derived class, no matter how many times it appears in the inheritance system, so it shares a 1 byte classX entity, with the addition of class Y and class Z, there will be 9 bytes. If there is alignment, it will be 12bytes, but the 1byte is omitted in vs2010, so there will be no alignment and it will be 8 bytes directly. The answer is finally uncovered !!!