1. Summary
in Cplusplus multi-inheritance programming often encountered such a problem-Kawai class implementation of multiple base class or interface inheritance, multi-base class or interface has the same member name, when the client and the implementation of the communication between the class compiler error "Can not use this, will produce ambiguity" due to a lot of solutions to this problem. For example, you can change the name of the same member. However, from a professional perspective, virtual inheritance may solve this problem. Then I'll look at how C + + avoids this problem.
2. Concept
when there is a common base class on multiple inheritance paths, the common base class will produce multiple instances (or multiple replicas) at a certain confluence of these paths, and the public base class can be described as a virtual base class if only one instance of the base class is to be saved. Class Derived classes Name: Virtual Inheritance Mode base class name
virtual is the keyword that declares that the base class is a virtual base class of derived classes.
For example:
Class Derived classes: Virtual base class 1,virtual base class 2,...,virtual base class N {...//derived class member declaration};
in the case of multiple inheritance, the virtual base class keyword has the same scope and inheritance as the keyword, and only works on the base class immediately following it. After a virtual base class is declared, the virtual base class maintains a copy of the same base class sub-object, along with the derived class, throughout the further derivation process. C + + uses virtual inheritance (inheritance), which solves the problem of data inconsistency between data members with the same name inherited from different paths, with different copies in memory, and sets the common base class to the virtual base class. A data member with the same name inherited from a different path has only one copy in memory, and the same function name has only one mapping. This brings a bit to solve the two semantic problems, but also save memory, to avoid the problem of inconsistent data.
3. Use Cases
Ambiguity:
#include <iostream>using namespace std; //base class base{ public: base () {cout << "base called ..." <<&NBSP;ENDL; void print () {cout << "Base print ..." &NBSP;<<ENDL; private: }; //sub class sub //defines a class sub {public: sub () {cout << "sub called ..." &NBSP;<<&NBSP;ENDL;} void print () {cout << "Sub print ..." &NBSP;<<&NBSP;ENDL; Private:}; //child class child : public base , public sub //defines a class child inherit from base ,sub { public: child respectively () {cout < < "child called ..." &NBSP;<<&NBSP;ENDL;} private: }; int main (int argc, char* argv[]) { Child c; //can not use this, will produce two Italian, VC under ERROR&NBSP;C2385&NBSP;&NBSP;&NBSP;//C.PRint (); //can only be used this way c.base::p rint (); c.sub::p rint (); system ("pause"); return 0; }
Multiple inheritance:
Description: C + + Virtual Inheritance Learning Demo //environment: vs2005 //blog:pppboy.blog.163.com //------------------- --------------------------------- #include "stdafx.h" #include <iostream >using namespace std; int gFlag = 0; class Base {public: base () {cout << "base called : " << gflag++ << endl;} void print () {cout << "Base print" &NBSP;<<ENDL;} };class mid1 : public base { public: mid1 () { cout << "mid1 called" &NBSP;<<&NBSP;ENDL;} private: };class Mid2 : public Base {public: mid2 () {cout << "mid2 called" &NBSP;<<&NBSP;ENDL;} };class child:public mid1, pubLic mid2 {public: child () {cout << "Child called" << endl;} };int main (int argc, char* argv[]) {child d;//can not be used in this way, will produce two of the meaning of //d.print (); //can only be used this way d.mid1::p rint ();d. Mid2:: print (); System ("pause"); return 0; }
Output
Base called:0
Mid1 called
Base called:1
Mid2 called
Child called
Base Print
Base Print
Virtual Inheritance:
#include "stdafx.h" #include <iostream>using namespace std; Int gflag = 0; class base {public: base () {cout < < "base called : " &NBSP;<<&NBSP;GFLAG++&NBSP;<<&NBSP;ENDL;} void print () {cout << "Base print" &NBSP;<<ENDL;} };class mid1 : virtual public base {public: mid1 () { cout << "mid1 called" &NBSP;<<&NBSP;ENDL;} private: };class mid2 : virtual public base {public : mid2 () {cout << "mid2 called" &NBSP;<<&NBSP;ENDL;} };class child:public mid1, public mid2 {public: child () { cout << "child called" &NBSP;<<&NBSP;ENDL;} };int main (int argc,&Nbsp;char* argv[]) {child d;//can be used in this way d.print ();//You can also use &NBSP;&NBSP;D.MID1:: Print ();d. Mid2::p rint (); System ("pause"); return 0; }
4. Summary
in the case of multiple inheritance, the virtual base class keyword has the same scope and inheritance as the keyword, and only works on the base class immediately following it. After a virtual base class is declared, the virtual base class maintains a copy of the same base class sub-object, along with the derived class, throughout the further derivation process. The construction order of the class constructor is observed, and copies are only one copy.
5. Expansion
Programmers in Windows programming encounter such a problem when they are doing COM programming------inherit interface IUnknown this piece uses non-virtual inheritance. What is this for? If there is such a doubt is normal. This is caused by a vtbl that is incompatible with COM. Like what:
struct Ix:public IUnknown
{
//....
};
struct Iy:public Iunknow
{
//....
};
Client program implementation:
... if (iid = = IID_IUnknown) {//the client wants the IUnknown interface. *PPV = static_cast<ix*> (this); } else if (iid = = Iid_ix) {//the client wants the IX interface. *PPV = static_cast<ix*> (this); } else if (iid = = Iid_iy) {*PPV = static_cast<iy*> (this); } ...
Visible, they are converted by type in the program. Otherwise, the first three functions in the VTBL of IX and IY will not point to the three member functions of IUnknown.
This article is from the "GDT Commentary" blog, make sure to keep this source http://844133395.blog.51cto.com/3483632/1767057
C + + Virtual inheritance Commentary