Доступ к функции базового класса
class Base
{
public: void foo(){}
};
class Derived : public Base
{
private:
using Base::foo;
};
int main()
{
Derived d;
d.foo();
}
Является ли код законным? Объявление using Base::foo
находится в частном разделе производного класса. Поэтому вызов d.foo()
не должен компилироваться, я прав?
Ответы
Ответ 1
В стандарте в разделе 11.2/4 говорится:
Член m доступен, если он указан в классе N, если
- m в качестве члена N является общедоступным или
- m в качестве члена N является приватным, а ссылка встречается у члена или друга класса N или
- m в качестве члена N защищен, а ссылка встречается у члена или друга класса N или в член или друг класса P, полученного из N, где m как член P является частным или защищенным, или
- существует базовый класс B из N, доступный в точке ссылки, и m доступен, когда он назван в классе B.
Однако в Стандарте также говорится, что
§11.3/1 "Доступ к члену базового класса может быть изменен в производном классе.
В вашем коде доступ члена foo
был изменен в производном классе. Поэтому код не должен компилироваться, но это все еще активная проблема с открытым статусом. Некоторые компиляторы компилируют код ( Comeau и Intel С++), тогда как g++ и MSVС++ (правильно) отклоняют его.
Ответ 2
Right.
Теперь проверка реальности & hellip;
MinGW g++ 4.4.1:
x.cpp: В функции 'int main()': x.cpp: 3: ошибка: 'void Base:: foo()' является недоступный
x.cpp: 15: ошибка: внутри этот контекст
Visual С++ 10.0:
x.cpp(15): ошибка C2248: 'Derived:: foo': не может получить доступ к приватным член, объявленный в классе "Производные"
x.cpp(9): см. объявление "Производные:: foo"
x.cpp(6): см. объявление "Производные"
Comeau Online 4.3.10.1:
В строгом режиме, с -tused, Compile удалось (но помните, Комо онлайн-компилятор не ссылается). Скомпилирован с расширениями С++ 0x включен.
К сожалению. И Комо - тот, который почти всегда прав! Ну, отключив расширения С++ 0x, для С++ 98/С++ 03:
В строгом режиме, с -tused, Compile удалось (но помните, Комо онлайн-компилятор не ссылается). Скомпилирован с расширениями С++ 0x Disabled.
Oops!
Ну, ты, майор мой, как говорят в Норвегии (буквально переведен на английский).
Я постараюсь сообщить об этом Комо.
РЕДАКТИРОВАТЬ: так как Прасун также ответил, цитируя Священный стандарт своей интерпретацией того, что противоречит тому, что я написал выше, хорошо, хорошо, standadeese & hellip;
§11.3/1 "Доступ элемента базового класса может быть изменен в производном классе & hellip;" и т.д., что так ясно, как может быть (не требуется интерпретация). И с конкретным примером. И нормативный текст, указывающий, что это эквивалентно объявлению using
.
Приветствия и hth.,
Ответ 3
using
- это объявление пространства имен в этом примере (в отличие от директивы пространства имен). Это не объявление метода, поскольку вы, похоже, собираетесь использовать его как.
Метод foo()
является общедоступным в классе Base
и по-прежнему доступен в классе Derived
.
Кажется, вы намерены сделать класс foo()
класса Base
недоступным. Хотя может быть и способ сделать это (я бы не знал, у меня никогда не было причины его попробовать), я предлагаю, чтобы это указывало на ошибку с логикой вашего наследования, и вы можете подумать о перепроектировании у наших классов.
Если ваш класс Derived
не будет вести себя как класс Base
, он не должен наследоваться от класса Base
.