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

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

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<Base&> (child).Foo(); // Okay. Foo is public in this context.
}

Этот юридический C ++? Причем «Этот» изменяющийся режим доступа виртуальной функции в производном классе.

26
задан hlx236sk 26 January 2010 в 17:20
поделиться

4 ответа

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

Это аналогичное в форме в форме, но различно в намерениях , не виртуальный интерфейс IDIOM. Некоторые обоснование дано здесь :

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

Поэтому к тому, почему вы на самом деле сделаете что-то в базе, но частные в производстве без Private или защищены Наследование Отказ

15
ответ дан 28 November 2019 в 07:16
поделиться

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

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

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

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

5
ответ дан 28 November 2019 в 07:16
поделиться

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

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

В данном конкретном случае, Child не имеет никакого дела, делая переопределенную виртуальную функцию приватной: разве она не должна реализовывать публичный интерфейс Base, так что отношение "есть-а" держится? (Если бы вы не использовали публичное наследование, что означает "Child is a Base", ваш трюк не сработал бы)

.
4
ответ дан 28 November 2019 в 07:16
поделиться

Это законно C ++, §11.6 / 1 говорит:

Доступ проверяется в точке вызова Использование типа используемого выражения обозначить объект, для которого Функция участника называется (B * в Пример выше). Доступ Функция участника в классе, в котором Это было определено (D в примере Выше) в целом не известно.

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

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

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

21
ответ дан 28 November 2019 в 07:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: