2016-09-07 3 views
2

У меня есть проблема наследования: Скажем, у меня естьC++ наследование - неоднозначные функции

class Time{ 
protected: 
void foo(); 
}; 

, а также

class Base: private Time{ 
void foo1(){ foo(); } 
}; 

class Child: public Base, private Time{ 
void foo2(){ foo(); }// here my compiler says that foo is ambiguous 
}; 

почему Foo() неоднозначен, если наследование Время в базе закрыто?

PS. Только & только для тех, кто должен видеть полный код, вот проект GitHub: https://github.com/huntekah/Interior_decorator-OpenGL_Project/blob/master/Grafika-OpenGL/Interior_decorator/Display.cpp#L133 класс Время (каталог утилит) наследуется ControlObjects и ControlCamera, оба из которых являются базой для элементов управления. Дисплей наследует элементы управления и дополнительно Time. commented line показывает место, где SetDeltaTime() неоднозначно;

+0

частный не скрывает. – Jarod42

+0

Потому что как 'Base', так и' Time' имеют функцию-член с именем 'foo', и компилятор не знает, какой из них вы пытаетесь вызвать. Там что-то обманывает. –

+0

будет ли пространство имен внутри базы скрывать? –

ответ

0

Предварительные замечания

Ваш фрагмент кода не компилировать по другой причине: Base не имеет доступа к Time «s foo() как это частный член. Таким образом, foo1() вызывает ошибку, прежде чем у вас возникнет двусмысленность.

Если изменить Time сделать защищенный его членом, то вы можете воспроизвести вашу ошибку точно так, как вы описали:

class Time{ 
protected: 
    void foo(); 
}; 

Что здесь не так?

Base частным образом наследует Time, так что его члены не должны быть видимыми для внешнего мира.

Но что может быть справедливо для внешнего мира, неверно для производных классов. Правила поиска имен в случае вывода говорят, что сначала имя ищется в иерархии классов, то перегрузка применяется, чем только контроль доступа осуществляется:

10.2/1 Member name lookup determines the meaning of a name (id-expression) in a class scope. Name lookup can result in an ambiguity, in which case the program is ill-formed. For an id-expression, name lookup begins in the class scope of this; for a qualified-id, name lookup begins in the scope of the nested-name-specifier. Name lookup takes place before access control.
10.2/8 If the name of an overloaded function is unambiguously found, overloading resolution also takes place before access control. Ambiguities can often be resolved by qualifying a name with its class name.

Как использовать множественное наследование:

Time  
    : 
    : 
Base Time 
    \ : 
    \ : 
    Child 

Таким образом, вы наследуете дважды foo(), один раз через личное наследование и onve через public. Эта неоднозначность делает имя foo в foo2() неоднозначным в соответствии со стандартом и до того, как будет проверен доступ, что сделает ваш код недействительным.

Обратите внимание, что Child видит 2 foo(), но по иронии судьбы не может использовать ни один из них: оба передаются через частный унаследованный. Поэтому, даже если вы разрешите двусмысленность, вы получите еще одно сообщение об ошибке.

1

есть еще одна ошибка в вашем коде: класс base наследует конфиденциально из класса Time и класс Child наследует снова конфиденциально из класса time !!!

закон наследования:

class Time 
{}; 

class Base : private Time 
{}; 

class Child : public Base, private Time 
{}; 

База имеет копию класса времени, потому что он наследует от него.

У ребенка есть экземпляр класса Base, потому что он наследует его.

*** Ребенок имеет экземпляр класса Time, поскольку его родители (База) имеют эту копию.

Если Child пытается наследовать явно из класса Time выдаст ошибку времени компиляции: ошибка C2584: «Ребенок»: прямая база «Время» недоступна; уже база «Базы»

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