C ++ virtual Inheritance Analysis and Object Model
The definition of virtual inheritance and virtual base classes is very simple, but in C ++, virtual inheritance exists as a relatively uncommon but absolutely necessary component, in addition, its behavior and model both show a huge difference (including differences in access performance) between the General inheritance system and the general inheritance system. Now we are studying virtual inheritance and virtual base classes.
Definition:
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:
Classcsubclass: virtual public cbase {};
Among them, cbase is called the csubclass virtual base class, rather than the cbase is a virtual base class, because cbase can not be the base class in the virtual inheritance system.
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:
Class base
{
Public:
Base (int n)
{
This-> m_base = N;
}
Virtualvoid F () {cout <"base: F ()" <Endl ;}
Intm_base;
};
Class subbase1: virtualpublic Base
{
Public:
Subbase1 (int A): Base ()
{
This-> m_subbase1 =;
}
Virtualvoid g () {cout <"subbase1: G ()" <Endl ;}
Int m_subbase1;
};
Class subbase2: virtualpublic Base
{
Public:
Subbase2 (int A): Base ()
{
This-> m_subbase2 =;
}
Virtualvoid H () {cout <"subbase1: H ()" <Endl ;}
Int m_subbase2;
};
Classderived: Public subbase1,
Public subbase2
{
Public:
Derived (int B): Base (B), subbase1 (B), subbase2 (B)
{
M_derived = B;
}
Virtualvoid K () {cout <"derived: K ()" <Endl ;}
Intm_derived;
};
Classsubderived: Public derived
{
Public:
Subderived (int K): Base (K), derived (k)
{
}
};
Note the content in the constructor initialization list of the derived and subderived classes in the above Code. It can be found that the initialization of the virtual base class base is included. Without this initialization statement, it will cause a compilation error. Why?
Lab environment (Windows 7 x64 + Visual Studio 2010)
Model Analysis:
Single virtual inheritance:
Test code:
# Include "stdafx. H"
# Include <iostream>
Usingnamespacestd;
Class base
{
Public:
Base (int n)
{
This-> m_base = N;
}
Virtualvoid F () {cout <"base: F ()" <Endl ;}
Intm_base;
};
Class subbase1: virtualpublic Base
{
Public:
Subbase1 (int A): Base ()
{
This-> m_subbase1 =;
}
Virtualvoid g () {cout <"subbase1: G ()" <Endl ;}
Int m_subbase1;
};
Int _ tmain (intargc, _ tchar * argv [])
{
/* Derived D (5 );
Subderivedf (6 );*/
Fun pfun = NULL;
Subbase1 SB1 (5 );
Subbase1 * sp = & SB1;
Cout <"sizeof (subbase1) =" <sizeof (SB1) <Endl;
Cout <"the address of vfptr_subbase1:" <(int *) * (int *) sp <Endl;
Pfun = (fun) * (int *) SP );
Pfun ();
Cout <"the address of vfptr_base:" <(int *) * (int *) SP + 3) <Endl;
Pfun = (fun) * (int *) SP + 3 ));
Pfun ();
System ("pause ");
Return 0;
}
Running result:
Object Memory Model diagram: (subbase1 Object Model)
Multiple virtual inheritance:
// Demo. cpp? Control? ? Servers required | used? What is the degree of degree in the descending order of Cheng Yu? Input? Loose ?. Zookeeper
//
# Include "stdafx. H"
# Include <iostream>
Usingnamespacestd;
Class base
{
Public:
Base (INT n = 1)
{
This-> m_base = N;
}
Virtualvoid F () {cout <"base: F ()" <Endl ;}
Intm_base;
};
Class subbase1: virtualpublic Base
{
Public:
Subbase1 (int A = 2)
{
This-> m_subbase1 =;
}
Virtualvoid g () {cout <"subbase1: G ()" <Endl ;}
Int m_subbase1;
};
Class subbase2: virtualpublic Base
{
Public:
Subbase2 (int A = 3)
{
This-> m_subbase2 =;
}
Virtualvoid H () {cout <"subbase2: H ()" <Endl ;}
Int m_subbase2;
};
Classderived: Public subbase1,
Public subbase2
{
Public:
Derived (int B = 4)
{
M_derived = B;
}
Virtualvoid K () {cout <"derived: K ()" <Endl ;}
Intm_derived;
};
Classsubderived: Public derived
{
Public:
Subderived (int K)
{
}
};
Typedefvoid (* Fun) (void );
Int _ tmain (intargc, _ tchar * argv [])
{
/* Derived D (5 );
Subderivedf (6 );*/
Fun pfun = NULL;
Derived SB1 (8 );
Derived * sp = & SB1;
Cout <"sizeof (subbase1) =" <sizeof (SB1) <Endl;
Cout <"the address of vfptr_subbase1:" <(int *) * (int *) sp <Endl;
Pfun = (fun) * (int *) SP );
Pfun ();
Cout <"the address of vfptr_deriverd:" <(int *) * (int *) SP + 1) <Endl;
Pfun = (fun) * (int *) SP + 1 ));
Pfun ();
Cout <"the address of vfptr_subbase2:" <(int *) * (int *) SP + 3) <Endl;
Pfun = (fun) * (int *) SP + 3 ));
Pfun ();
Cout <"the address of vfptr_base:" <(int *) * (int *) SP + 7) <Endl;
Pfun = (fun) * (int *) SP + 7 ));
Pfun ();
System ("pause ");
Return 0;
}
Result:
Object Memory Model diagram: (deirved Object Model)
Experiment conclusion:
1. Virtual inheritance is different from normal inheritance. The virtual base class is placed at the end of the object memory. Each subclass finds the virtual base class by offset.
2. A vbptr pointer (virtual base class Table pointer) is added to the virtual inheritance, pointing to the virtual base class.
3. vbptr points to a table with the address offset.
Project |
Description |
First: offset to this class |
-4: when there is a virtual function; 0: No virtual function |
Item 2: offset to the virtual base class |
|
Item 3: 0 |
Split. In actual memory, the two virtual base classes of subbase1 and subbase2 are put together. |