|
||||
|
Section 25:
|
[25.8] What is the "dreaded diamond"?
The "dreaded diamond" refers to a class structure in which a particular class appears more than once in a class's inheritance hierarchy. For example,
class Base {
public:
...
protected:
int data_;
};
class Der1 : public Base { ... };
class Der2 : public Base { ... };
class Join : public Der1, public Der2 {
public:
void method()
{
data_ = 1; ← bad: this is ambiguous; see below
}
};
int main()
{
Join* j = new Join();
Base* b = j; ← bad: this is ambiguous; see below
}
Forgive the ASCII-art, but the inheritance hierarchy looks something like
this:
Base
/ \
/ \
/ \
Der1 Der2
\ /
\ /
\ /
Join
Before we explain why the dreaded diamond is dreaded, it is important to note
that C++ provides techniques to deal with each of the "dreads." In other
words, this structure is often called the dreaded diamond, but it
really isn't dreaded; it's more just something to be aware of.
The key is to realize that Base is inherited twice, which means any data members declared in Base, such as data_ above, will appear twice within a Join object. This can create ambiguities: which data_ did you want to change? For the same reason the conversion from Join* to Base*, or from Join& to Base&, is ambiguous: which Base class subobject did you want? C++ lets you resolve the ambiguities. For example, instead of saying data_ = 1 you could say Der2::data_ = 1, or you could convert from Join* to a Der1* and then to a Base*. However please, Please, PLEASE think before you do that. That is almost always not the best solution. The best solution is typically to tell the C++ compiler that only one Base subobject should appear within a Join object, and that is described next. |
|||