2014-01-17 3 views
2

Я пытаюсь выполнить следующие классы:C++ Multiple и виртуальное наследование

class a { 
public : 
    //... 
    f(); 
    //... 
}; 

class b : virtual public a { 
public : 
    //... 
    f(); 
    //... 
} 

class c : virtual public a { 
public : 
    //... 
    f(); 
    //... 
} 

class d : virtual public c { 
public : 
    //... 
    f(); 
    //... 
} 

class e : public b, public d { 
public : 
    //... 
} 

но компилятор говорит мне, что запрос функции члена F() является неоднозначным. Я хочу, чтобы 'e' наследовал от f() версии 'd' (так что 'c'), но код компилируется, только если я переработал f() в 'e'. Таким образом, я могу скомпилировать, только если я закодировать «е» конструктор следующим образом:

e::e(...) : a(...), c(...), b(...), d(...) 
{ 
} 

Что кажется нелогичным для меня, так как «D» inherate из «с» и «B» будет построен первым.

ответ

1

e наследуется от b & d, поэтому существует b версия f() и d версии f().

Очень логично, что существует двусмысленность.

Если вы хотите класс е использовать D версию F(), есть два способа,

  1. вызова d :: F() непосредственно в вызове

    instance_e.d::f(); //will call d::f().

  2. переобъявить :: д е() в е

    class e : public b, public d { public : using d::f; }

Не понимаю, почему вы здесь упоминаете конструктор, порядок выполнения не влияет на функцию f().

+0

+1 - использование d :: f; 'является хорошим вариантом. Третий способ заключается в добавлении 'void f() {d :: f(); } 'to' class e' - здесь не обязательно, но иногда полезно при изменении аргументов, входе в журнал добавлено и т. д. –

+0

Просто потому, что я не понимаю, почему компилятор хотел, чтобы я построил конструктор в этом конкретном порядке, поскольку , на мой взгляд, b должен был быть построен первым. Спасибо за ваш ответ, но я буду использовать метод «использования». – Kernael

2

Это не имеет значения при заказе строительства или декларации. Если есть 2 базовых класса с одним и тем же именем метода, компилятор не может определить, какой из них вы хотите вызвать. В вашем случае у вас есть переопределенная версия f() как в классе b, так и в классе d.

Так что сделайте вызов явным. b :: f() или d :: f().

Смежные вопросы