В случае одиночного наследования указатель, ссылка или объект производного класса при необходимости автоматически преобразуются в указатель, ссылку или объект базового класса, которому открыто наследует производный. Это остается верным и для множественного наследования. Так, указатель, ссылку или сам объект класса Panda можно преобразовать в указатель, ссылку или объект ZooAnimal, Bear или Endangered:
extern void display( const Bear& );
extern void highlight( const Endangered& );
Panda ying_yang;
display( ying_yang ); // правильно
highlight( ying_yang ); // правильно
extern ostream&
operator<<( ostream&, const ZooAnimal& );
cout << ying_yang << endl; // правильно
Однако вероятность неоднозначных преобразований при множественном наследовании намного выше. Рассмотрим, к примеру, две функции:
extern void display( const Bear& );
extern void display( const Endangered& );
Неквалифицированный вызов display() для объекта класса Panda
Panda ying_yang;
display( ying_yang ); // ошибка: неоднозначность
приводит к ошибке компиляции:
Error: display( ying_yang ) -- ambiguous, one of
display( const Bear& );
display( const Endangered& );
Ошибка: display( ying_yang ) -- неоднозначно, одна из
display( const Bear& );
display( const Endangered& );
Компилятор не может различить два непосредственных базовых класса с точки зрения преобразования производного. Равным образом применимы обе трансформации. (Мы покажем способ разрешения этого конфликта в разделе 18.4.)
Чтобы понять, какое влияние оказывает множественное наследование на механизм виртуальных функций, определим их набор в каждом из непосредственных базовых классов Panda. (Виртуальные функции введены в разделе 17.2 и подробно обсуждались в разделе 17.5.)
class Bear : public ZooAnimal {
public:
virtual ~Bear();
virtual ostream& print( ostream& ) const;