Deep analysis of the knowledge of base class and base class inheritance in C + + programming _c language

Source: Internet
Author: User
Tags inheritance

Base class
The inheritance process creates a new derived class that consists of the members of the base class plus any new members added by the derived class. In multiple inheritance, you can build an inheritance diagram in which the same base class is part of multiple derived classes. The following illustration shows this class of diagrams.

Multiple instances of a single base class
In the diagram, a graphical representation of the components of collectiblestring and collectiblesortable is shown. However, the base class collectible is located in Collectiblesortable through the collectiblesortablestring path and the collectiblestring path. To eliminate this redundancy, you can declare it as a virtual base class when inheriting such a class.

Multiple base classes
as described in multiple inheritance, a class can derive from more than one base class. In a multiple-inheritance model where a class derives from multiple base classes, use the base-list syntax element to specify the base class (see the "Syntax" section in the overview). For example, you can specify a class declaration that derives from the book of Collectionofbook and Collection:

//compile with:/ld
class Collection {
Class Book {};
Class Collectionofbook:public book, public Collection {
 //NEW members

It is not important to specify the order of the base class, except that in some cases the constructors and destructors are invoked. In these cases, the order in which the base class is specified affects:
The order in which constructors are initialized. The order of the specifications is important if your code relies on the Collection part of the collectionofbook that you want to initialize before the book part. Executes the initialization in the order of the classes specified in Base-list.
The order in which the destructor is called for cleanup. Similarly, the order is important if you must render a specific "part" of the class when you destroy another part. Call the destructor in the reverse order of the classes specified in Base-list.
The canonical order of the base class affects the memory layout of the class. Do not make any programming decisions based on the order of the base members in memory.
You cannot specify the same class name multiple times when Base-list is specified. However, you can use a class multiple times as an indirect base for a derived class.

Virtual base class
because a class may be the indirect base class of a derived class multiple times, C + + provides a way to optimize how this base class works. Virtual base classes provide a way to save space and to avoid ambiguity in class hierarchies that use multiple inheritance.
Each Non-virtual object contains a copy of the data member defined in the base class. This duplication wastes space and requires that you specify a copy of the required base class member each time you access the base class member.
When a base class is specified as a virtual base, the base class can act as an indirect base multiple times without duplicating its data members. A single copy of a data member of a base class is shared by all base classes that use it as a virtual base.
When you declare a virtual base class, the dummy keyword appears in the base list of the derived class.
Consider the class hierarchy in the following illustration, which demonstrates a simulated lunch queue.

Simulated Lunch Queue Chart
In this diagram, the Queue is the base class for Cashierqueue and Lunchqueue. However, when you combine these two classes into Lunchcashierqueue, the following problem occurs: The new class contains two child objects of the type Queue, one from Cashierqueue and the other from Lunchqueue. The following illustration shows the conceptual memory layout (the actual physical memory layout may be optimized).

Mock Lunch Queue Object
Note that there are two Lunchcashierqueue child objects in the Queue object. The following code declares the Queue as a virtual base class:

//compile with:/ld
class Queue {};
Class Cashierqueue:virtual public Queue {};
Class Lunchqueue:virtual public Queue {};
Class Lunchcashierqueue:public Lunchqueue, public Cashierqueue {};

The virtual keyword ensures that only one copy of the child object Queue is included (see the following figure).

Simulate a lunch queue object using a virtual base class
A class can have both virtual and non-virtual components of a given type. The following illustration illustrates this situation.

Virtual components and non-virtual components of the same class
In the diagram, Cashierqueue and Lunchqueue use the Queue as the virtual base class. However, Takeoutqueue specifies the Queue as a base class instead of a virtual base class. Therefore, Lunchtakeoutcashierqueue has two child objects of type Queue: one from the inherited path containing the Lunchcashierqueue and the other from the path containing the takeoutqueue. This is demonstrated in the following illustration.

Object layout with virtual and non-virtual inheritance
virtual inheritance provides a significant size advantage compared to non-virtual inheritance. However, it may introduce additional processing overhead.
If a derived class overrides a virtual function it inherits from a virtual base class, and the constructor or destructor of the derived base class invokes the virtual function with a pointer to the dummy base class, the compiler may introduce other hidden "vtordisp" fields into the class that has the virtual base. The/VD0 compiler option disables the addition of hidden Vtordisp constructor/destructor substitution members. The default/VD1 compiler option enables them when necessary. Turn off Vtordisps only when you are sure that all class constructors and destructors will call virtual functions in a fictitious manner.
The/VD compiler option affects the entire compilation module. You can use the vtordisp pragma to disable the Vtordisp field on a class-by-type basis, and then re-enable the fields:

#pragma vtordisp (off)
class Getreal:virtual public {...};
#pragma vtordisp (ON)

For the preceding class declaration, the code shown below is ambiguous, because B refers to B in a or B is not clear:

c *pc = new C;

Pc->b ();

Name Ambiguity
multiple inheritance makes it possible to inherit names along multiple paths. Class member names along these paths are not necessarily unique. These name conflicts are called "ambiguities."
Any expression that references a class member must take a clear reference. The following example shows how to create ambiguity:

//compile with:/ld
//Declare Two base classes, A and B.
Class A {public
 unsigned A;
 unsigned b ();

Class B {public
 unsigned A ();//Note This Class A also has a member "a"
 int B ();  and a member "B".
 char c;

Define class C as derived from A and B.
Class C:public A, public B {};

Take a look at the previous example. Because name a is a member of Class A and class B, the compiler cannot argue which a specifies that the function will be invoked. If a member can reference more than one function, object, type, or enumerator, access to that member is ambiguous.
The compiler detects ambiguity by executing tests in this order:
If access to the name is ambiguous (as described above), an error message is generated.
If overloaded functions are explicit, they are parsed. (For more information about function overload ambiguity, see parameter matching.) )
If access to the name violates member access, an error message is generated. (For more information, see member access control.) )
When an expression is ambiguous through inheritance, you can manually eliminate the ambiguity by qualifying the name in consideration and its class name. To properly compile the above example without ambiguity, use the following code:

c *pc = new C;

Pc->b::a ();

When you declare C, if you refer to C in the scope of B, you may cause an error. However, no errors are made until the unqualified reference to C is actually created in the scope of B.
It is possible to reach multiple names (functions, objects, or enumerators) through an inheritance diagram. This situation is considered to be ambiguous when used in conjunction with a non-virtual base class. These names are not intended to be used with the virtual base class unless one of the names "determines" another name.
If a name is defined in two classes and one class derives from another, the name can control another name. The base name is the name in the derived class, which should be used when ambiguity should occur, as shown in the following example:

//compile with:/ld
Class A {public
 int A;

Class B:public virtual A {public
 int A ();

Class C:public virtual A {};

Class D:public B, public C {public
 D () {a ();}//Not ambiguous. B::a () dominates a::a.

Ambiguous conversions
an explicit or implicit conversion from a pointer to a class type or a reference to a class type can cause ambiguity. The following illustration (an ambiguous conversion to a pointer to a base class) shows the contents of:
A declaration of an object of type D.
Applies the address-of operator (&) to the effect of the object. Note that the address-of operator always provides the base address of the object.
Explicitly converts the pointer obtained using the ADDRESS-OF operator to the effect of the base class type A. Note that casting the address of this object to a * type does not always provide sufficient information for the compiler to select a child object of type A, in which case there will be two child objects.

Ambiguous conversion of pointer to base class
The conversion to type A * (a pointer to a) is ambiguous because it is not possible to identify which child of type A is correct. Note that you can avoid ambiguity by explicitly specifying the child objects you want to use, as follows:

(A *) (b *) &d  //use B subobject.
(A *) (c *) &d  //Use C subobject.

Polysemy and virtual base classes
If you use a virtual base class, functions, objects, types, and enumerators can be reached through multiple inheritance paths. Because there is only one instance of the base class, there is no ambiguity when accessing the names.
The following illustration shows how to use virtual and non-virtual inheritance to compose objects.

Virtual and non-virtual derivations
In the figure, accessing any member of Class A through a non-virtual base class will result in two semantics, and the compiler does not explain whether to use child objects associated with B or child objects associated with C. However, when you designate a as a virtual base class, it is not a problem to access which child objects.

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: 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.