Рассмотрим приведенный ниже фрагмент кода.
Метод Sayhi () имеет открытый доступ в классе Base.
Sayhi () был переопределен как приватный метод классом Derived.
Таким образом, мы можем вторгаться в чью-то личную жизнь и C ++ не может обнаружить это, потому что все происходит во время выполнения.
Я понимаю, что это «чисто» проверка во время компиляции. Но при использовании некоторой иерархии наследования программисты могут неправильно изменять спецификаторы доступа. Разве стандарт не должен сказать, по крайней мере? какое-то предупреждающее сообщение.
Почему компилятор не выдает по крайней мере предупреждающее сообщение, когда спецификатор доступа переопределенных или виртуальных функций отличается?
Q1. Говорит ли стандарт C ++ о таких аномалиях во время выполнения?
Q2. Я хочу понять, с точки зрения стандарта C ++, почему бы стандарту не предписать разработчикам компилятора диагностику предупреждений?
#include <iostream>
class Base {
public:
virtual void Sayhi() { std::cout<<"hi from Base"<<std::endl; }
};
class Derived : public Base
{
private:
virtual void Sayhi() { std::cout<<"hi from Derived"<<std::endl; }
};int main() {
Base *pb = new Derived;
// private method Derived::Sayhi() invoked.
// May affect the object state!
pb->Sayhi();
return 0;
}
Говорит ли стандарт C ++ о таких аномалиях во время выполнения?
Нет. Контроль доступа осуществляется только во время компиляции и влияет на то, какие имена можно использовать, а не на какие функции можно вызывать.
Так что в вашем примере вы можете получить доступ к имени Base::Sayhi
, но нет Derived::Sayhi
; и доступ к Base::Sayhi
позволяет виртуально вызывать любую функцию, которая переопределяет ее.
Почему стандарт не заставляет разработчиков компиляторов иметь диагностические предупреждения?
Стандарт вообще ничего не говорит о предупреждениях; это просто определяет поведение правильно сформированного кода. Авторы компилятора должны решить, какие предупреждения могут быть полезны; и предупреждение обо всех приватных переопределениях на тот случай, если вы не хотели, чтобы они были переопределены, звучит так, как будто это приведет к множеству ложных срабатываний.
Спецификация доступа не может быть ослаблена, ее можно только подтянуть.
Sayhi()
является public
в базовом классе, поэтому в основном все классы, производные и переопределенные из него, должны ожидать, что метод public
нет вторжения. Спецификация доступа для функций переопределения хорошо определена, так как метод был объявлен public
начать с.
Даже если на ваш вопрос уже дан ответ, я хотел бы добавить примечание.
Пока вы считаете это «аномалией» и хотели бы провести диагностику, на самом деле это полезно: вы можете гарантировать, что ваша реализация может использоваться только полиморфно. Производный класс должен иметь только открытый ctor и никаких других открытых функций, все вновь реализованные функции-члены должны быть закрытыми.