1.1. Multi-Inheritance
Multi-inheritance means that a class inherits from multiple parent classes. If multiple base classes have members of the same name, when referencing a member with a duplicate name in a derived class, the domain identifier must be used. Otherwise, the compiler cannot know which variable is referenced.
# Include
Class BaseA {protected: int _ mem ;};
Class BaseB {protected: int _ mem ;};
Class Derived: public BaseA, public BaseB
{
Public:
Derived (int a, int B) {BaseA: _ mem = a, BaseB: _ mem = B ;}
Inline int A (void) const {return BaseA: _ mem ;}
Inline int B (void) const {return BaseB: _ mem ;}
};
Int main (void)
{
Derived d (1, 2 );
Std: cout <"A =" <
Print (readme );
Dispose (readme );
Delete readme;
}
1.1.2. Base-From-Member usage
In boost, multiple inheritance is used to solve a problem called base-from-member [6]: that is, when the base class uses the member variables of the derived class during initialization through the constructor. Because the structure of a derived class is constructed after the base class is constructed, the members of the derived class are constructed only after all the base class constructor is executed. If the constructor of the derived class operates on the members of the class, the structure is unpredictable, and the C standard is undefined. For example:
# Include // for std: streambuf
# Include // for std: ostream
Class fdoutbuf: public std: streambuf
{
Public:
Explicit fdoutbuf (int fd );
//...
};
Class fdostream: public std: ostream
{
Protected:
Fdoutbuf buf;
Public:
Explicit fdostream (int fd): buf (fd), std: ostream (& buf)
{}
//...
};
Therefore, some technology must be used to ensure that the program will not operate on the objects that have not been constructed. R. samuel Klatchko uses another method to define a base class to solve this problem, because the class construction sequence is the same as the defined sequence, you only need to put the member definitions used by the base class in another base class and put them in front of the definition list. For example:
# Include // for std: streambuf
# Include // for std: ostream
Class fdoutbuf: public std: streambuf
{
Public:
Explicit fdoutbuf (int fd );
//...
};
Struct fdostream_pbase
{
Fdoutbuf sbuffer;
Explicit fdostream_pbase (int fd): sbuffer (fd)
{}
};
Class fdostream: private fdostream_pbase, public std: ostream
{
Typedef fdostream_pbase pbase_type;
Typedef std: ostream base_type;
Public:
Explicit fdostream (int fd)
: Pbase_type (fd), base_type (& sbuffer)
{}
//...
};
In this case, multi-inheritance is not necessary. Previously, the author used pointers to solve this problem in a project, the object pointed to by this pointer is created using new when initializing the list. The Code is as follows. Because when calling the ostream constructor, the parameter is actually a value expression, the value expression must be executed first, so that _ content is initialized first, because the pointer is of the POD type, this is also safe. Note that ostream constructor may throw an exception because the TDTPMessage object is not constructed successfully, so the Destructor will not be executed, therefore, the object pointed to by content _ may cause memory leakage. Therefore, you must use the function try block (function-try-block) in the code to capture exceptions that may be thrown by the base class constructor.
# Include
Class TDTPMessage: public ostream
{
Public:
TDTPMessage (void)
Try
: Ostream (content _ = new stringbuf ())
{/*...*/}
Catch (...){
If (content _! = NULL) delete content _;
/*...*/
Throw;
}
~ TDTPMessage (void) {if (content _! = NULL) delete content _;}
Private:
Std: stringbuf * content _;
};