Изменение режима доступа к функциям в производном classе

Рассмотрим следующий fragment:

struct Base { virtual ~Base() {} virtual void Foo() const = 0; // Public }; class Child : public Base { virtual void Foo() const {} // Private }; int main() { Child child; child.Foo(); // Won't work. Foo is private in this context. static_cast (child).Foo(); // Okay. Foo is public in this context. } 

Является ли это законным C ++? «Это» – изменение режима доступа виртуальной функции в производном classе.

Да, изменение режима доступа в производных classах является законным.

Это похоже на форму, но отличается от намерения к идиоме не виртуального интерфейса . Здесь приводится некоторое обоснование:

Дело в том, что существуют виртуальные функции для настройки; если они также не должны быть вызваны непосредственно из кода производных classов, нет необходимости когда-либо делать их чем-то, кроме частных.

Что касается того, почему вы на самом деле делаете что-то public в базе, но private в производном, не имеющем private или protected наследования, находится вне меня.

Это законный C ++, §11.6 / 1 гласит:

Доступ проверяется в точке вызова с использованием типа выражения, используемого для обозначения объекта, для которого вызывается функция-член (B * в приведенном выше примере). Доступ к функции-члена в classе, в котором он был определен (D в приведенном выше примере), вообще не известен.

Как вы отметили, Child::Foo() , таким образом, все еще доступен через базовый class, который в большинстве случаев нежелателен:

  Child* c = new Child; Base* b = c; c->Foo(); // doesn't work, Child::Foo() is private b->Foo(); // works, calls Child::Foo() 

В основном, декларация, на которую вы ссылаетесь в выражении, диктует режим доступа – но виртуальные функции подрывают это как другую функцию, тогда именованный может быть фактически вызван.

Это совершенно законный C ++. Вы просто определяете новый метод в classе Child.

Теперь он делает то, что вы хотите, чтобы это сделать, это другой вопрос. Я считаю, что режим доступа не является частью сигнатуры метода, а это значит, что вызов виртуального метода Base Foo в конечном итоге вызывает метод Child Foo.

Итак, вот вывод: это законный c ++, и он работает так, как вы ожидали.

Я не принимаю во внимание линию child.Foo(); который не может работать, потому что нет сомнений в том, что он пытается получить доступ к частному Foo () методу Child.

Кажется, он компилируется и вызывает правильный метод.

Помните, что спецификаторы доступа предназначены для помощи дисциплинированному программисту, а не для предотвращения любых попыток обойти его любой ценой.

В этом конкретном случае у ребенка нет бизнеса, делающего переопределенную виртуальную функцию приватной: не предполагается ли реализовать публичный интерфейс Base, поэтому имеет место отношение «is-a»? (Если вы не использовали публичное наследование, что означает «Ребенок – это база», трюк не будет работать.)

  • Как использовать конструкторы базового classа и оператор присваивания в C ++?
  • Как проверить, наследует ли class другой class, не создавая его?
  • Наследование конструктора Java
  • Почему невозможно расширять annotations в Java?
  • Что такое наследование конструктора?
  • Наследование в статических методах
  • Реализует vs extends: Когда использовать? Какая разница?
  • Как интерфейсы заменяют необходимость множественного наследования при наличии существующих classов
  • Цепочка метода + наследование плохо сочетается?
  • Статический polymorphism C ++ (CRTP) и использование typedefs из производных classов
  • Когда использовать интерфейс вместо абстрактного classа и наоборот?
  • Interesting Posts

    Улавливание кодов ошибок в оболочке

    Почему тип основной функции в C и c ++ оставлен пользователю для определения?

    USB-накопитель внезапно стал доступен только для чтения

    Установите прозрачный фон изображения на Android

    Приложение для маскировки паролей

    указатель указателя в связанном списке добавить

    Как удалить Windows 8 Consumer Preview?

    Vim удалить все строки, которые НЕ содержат определенное слово

    Как узнать файлы «.automaticDestinations-ms», к которым относится приложение?

    Hostdomonster Subdomain перенаправляется на домашний сервер IP: как ssh на домашний сервер с использованием субдомена

    Проверка формата адреса электронной почты с помощью Jquery.validate.js

    Как поймать исключение JNI / Java

    Сохранение заказа с помощью LINQ

    Можно ли маршрутизировать только конкретное приложение через VPN?

    Замена текста H1 на изображение логотипа: лучший способ для SEO и доступности?

    Давайте будем гением компьютера.