tr() and Internationalization
Multiple Inheritance
Multiple inheritance is a form of inheritance in which a class inherits the structure and behavior of more than one base class.
Common uses of multiple inheritance:
- For crossing the functionality of very different classes with little overlap, such as in Figure 23.1.
Figure 23.1. QWidget's inheritance
- For implementing a common "pure interface" (class with only pure virtual functions) in a variety of different ways.[2]
[2] As we see in Section 23.3.2.
Multiple inheritance hierarchies are more complex and are harder to design, implement, and understand than single inheritance hierarchies. They can be used to solve some difficult design problems, but should not be used if a simpler approach (such as aggregation) is feasible. As with single inheritance, multiple inheritance defines a static relationship among classes. It cannot be changed at runtime.
23.3.1. Multiple Inheritance Syntax
The example in this section demonstrates multiple inheritance syntax and usage.
The two base classes shown in Figure 23.2, Rectangle and ScreenRegion, each have particular roles to play on the screen. One class is concerned with shape and location, while the other is concerned with color and visibility characteristics. A Window must be a Rectangle and a ScreenRegion. They are defined in Example 23.6.
Figure 23.2. Window and ScreenRegion
Example 23.6. src/multinheritance/window.h
#include "color.h" #include "point.h" class Rectangle { public: Rectangle( Const Point& ul, int length, int width); Rectangle( const Rectangle& r) ; void move (const Point &newpoint); private: Point m_UpperLeft; int m_Length, m_Width; }; class ScreenRegion { public: ScreenRegion( Color c=White); ScreenRegion (const ScreenRegion& sr); virtual color Fill( Color newColor) ; void show(); void hide(); private: Color m_Color; // other members... }; class Window: public Rectangle, public ScreenRegion { public: Window( const Point& ul, int len, int wid, Color c) : Rectangle(ul, len, wid), ScreenRegion(c) {} <-- 1 Window( const Rectangle& rect, const ScreenRegion& sr) : Rectangle(rect), ScreenRegion(sr) {} <-- 2 // Other useful member functions ... }; (1)Use base class ctors. (2)Use base class copy ctors. |
There are some syntax items in the classHead of the derived class that deserve some attention.
- An access specifier, e.g., public or protected, must appear before each base class name if the derivation is not private.
- Default derivation is private.
- It is possible to have a mixture of public, protected, and private derivations.
- The comma (,) character separates the base classes.
- The order of base class initialization is the order in which the base classes are listed in the classHead.
Client code to put a Window on the screen is shown in Example 23.7.
Example 23.7. src/multinheritance/window.cpp
#include "window.h" int main() { Window w(Point(15,99), 50, 100, Color(22)); w.show(); <-- 1 w.move (Point(4,6)); <-- 2 return 0; } (1)calls ScreenRegion::show(); (2)calls Rectangle::move(); |
Member Initialization
Default initialization or assignment proceeds member by member in the order that data members are declared in the class definition: First, base classes; then, derived class members.
23.3.2. Multiple Inheritance with Abstract Interfaces
One situation where it is appropriate to use multiple inheritance is when more than one abstract interface is needed. Figure 23.3 shows a class diagram based on the MP3 Data Model assignment in Section 25.1. FileTagger inherits the DataObject/QObject for its signals and slots, as well as for its property() and setProperty() functions. FileTagger also needs the Mp3Song interface that defines all of the fields for which an ID3 tag should have getters/setters. Similarly, Mp3File needs both the DataObject and the Mp3Song interfaces, even though it is not connected to a physical MP3 file.
Figure 23.3. MP3 data model
Multiple inheritance can help reduce dependencies for client code. For example, a client function can have an Mp3Song parameter without needing id3lib or Qt in order to exploit the Mp3Song interface. Mp3Song, with only pure virtual functions, enforces the interface on all derived classes. Separating the interface from different implementations makes plugin-frameworks possible.
In Figure 23.3, QObject is one of the base classes that is multiply inherited. One restriction Qt has is that QObject must only be inherited once by each class; further, the QObject-derived base must be listed first in the list of base classes. Breaking this rule will lead to strange errors from the code generated by moc, the MetaObject compiler. |
Point of Departure
|