在百度的多重继承解释词条中有提到钻石问题,我去查了之后,整理如下:
钻石问题的英文称呼是“The Diamond Problem”,也有称为“Dreadful Diamond on Derivation”,Diamond可叫钻石,也可叫菱形,所以也可以说是“可怕的菱形派生”。
C++中是允许多重继承的,因此假设A是基类,B由A继承下来,C由A继承下来,并且D是由B与C多重继承下来,这样,它们的结构关系就是:
A
/ \
B C
\ /
D
这就是菱形的由来。那它有什么问题呢?由于C++我没有试过,只能从资料中推测出来,现在C#要用接口来实现,并且自己写具体的实现代码,因此这种问题应该不会再出来了吧。
翻译后的文童
在多重继承中避免菱形问题
多重继承是个十分有用的特性,但它会产生菱形问题,代码如下(变量也用了中文):
class 电子设备{
int 电压,
public:
int 获得电压 ( ) const { return 电压; }
} ;
class 收音机 : public 电子设备 { / * ...* / } ;
class 随身听 : public 电子设备 { / * ...* / } ;
class 带收音机的随身听: public 收音机, public 随身听 { / * ..* / } ;
int main( )
{
带收音机的随身听 rt ;
int 电压 = rt.获得电压() ;
/* 错误 - 不明确的调用。在rt中存在两个“获得电压()”。 */
}
带收音机的随身听是来自两个基类,每个基类又各自带有电子设备的数据成员与方法。因此,rt有两个“电子设备”的子对象。在本例中,你在要重复公共基类的地方,你必须使用virtual来继承。
class 收音机 : virtual public 电子设备 { / * ..* / } ;
class 随身听 : virtual public 电子设备 { / * ..* / } ;
class 带收音机的随身听: public 收音机, public 随身听 { / * ..* / }
现在带收音机的随身听只有一个公用的电子设备实例,因此不会不明确了。
int 电压 = rt.获得电压() ; //OK
注意:由于关键字virtual在“收音机”与“随身听”这两个类中,因此“电子设备”将只有一个实例对象,因此不会被混淆。
Pankaj Mishra
原文及出处如下:
http://www.devx.com/tips/Tip/32035
Avoid the Diamond Problem when Using Inheritance in Loops
While multiple inheritance is an extremely useful feature—escpecially in large scale software, it can also lead to a problem known as the DDD, or "Dreadful Diamond on Derivation," or simply "The Diamond Problem," shown in the following code:
class ElectricAppliance{
int voltage,
public:
int getVoltage ( ) const { return voltage; }
} ;
class Radio : public ElectricAppliance { / * ...* / } ;
class Tape : public ElectricAppliance { / * ...* / } ;
class RadioTape: public Radio, public Tape { / * ..* / } ;
int main( )
{
RadioTape rt ;
int voltage = rt .getVoltage( ) ;
/* Error - ambiguous call. Two copies getVoltage( ) exist in rt*/
}
RadioTape is derived simultaneously from two base classes, each of which has its own copy of the methods and data members of ElectricAppliance. Consequently, the object rt has two ElectricAppliance subobjects. In cases like this, where you need to reduplicate data methods from a common base class, you should use virtual inheritance:
class Radio : virtual public ElectricAppliance { / * ..* / } ;
class Tape : virtual public ElectricAppliance { / * ..* / } ;
class RadioTape: public Radio, public Tape { / * ..* / }
Now, class RadioTape contains a single shared instance of ElectricAppliance, so there are no ambiguities:
int voltage = rt .getVoltage( ) ; / /OK
Note: Because of the virtual keyword in the base-class portion of Radio and Tape, an instance of ElectricAppliance will have have only a single, base subobject. This eliminates the ambiguities.
Pankaj Mishra