Есть ли способ предотвратить переопределение метода в подклассах?

StackOverflow https://stackoverflow.com/questions/17483

  •  09-06-2019
  •  | 
  •  

Вопрос

Кто-нибудь знает о языковой функции или методе в C ++, позволяющем предотвратить переопределение дочерним классом определенного метода в родительском классе?

class Base {
public:
    bool someGuaranteedResult() { return true; }
};

class Child : public Base {
public:
    bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};

Даже если это не виртуальная функция, это все равно разрешено (по крайней мере, в компиляторе Metrowerks, который я использую), все, что вы получаете, это предупреждение во время компиляции о скрытии невиртуальной унаследованной функции X.

Это было полезно?

Решение

Пара идей:

  1. Сделайте свою функцию приватной.
  2. Не делайте свою функцию виртуальной.Однако на самом деле это не предотвращает затенение функции другим определением.

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

Удачи вам!

Другие советы

Когда вы можете использовать final спецификатор для виртуальных методов (введен в C ++ 11), вы можете это сделать.Позвольте мне процитировать мой любимый док-сайт:

При использовании в объявлении виртуальной функции final указывает, что функция не может быть переопределена производными классами.

Адаптированный к вашему примеру, который был бы похож:

class Base {
public:
    virtual bool someGuaranteedResult() final { return true; }
};

class Child : public Base {
public:
    bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};

При компиляции:

$ g++ test.cc -std=c++11
test.cc:8:10: error: virtual function ‘virtual bool Child::someGuaranteedResult()’
test.cc:3:18: error: overriding final function ‘virtual bool Base::someGuaranteedResult()’

Когда вы работаете с компилятором Microsoft, также взгляните на sealed ключевое слово.

Похоже, то, что вы ищете, является эквивалентом языка Java Финал ключевое слово, которое предотвращает переопределение метода подклассом.

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

(a) Я не думаю, что создание функции private является решением, потому что это просто скроет функцию базового класса от производного класса.Производный класс всегда может определить новую функцию с той же сигнатурой.(b) Сделать функцию невиртуальной также не является полным решением, потому что, если производный класс переопределяет ту же функцию, всегда можно вызвать функцию производного класса с помощью привязки времени компиляции, т.е. obj.someFunction() где obj является экземпляром производного класса.

Я не думаю, что есть способ сделать это.Кроме того, я хотел бы знать причину вашего решения запретить производным классам переопределять функции базового класса.

Для пояснения: большинство из вас неправильно поняли его вопрос.Он не спрашивает о "переопределении" метода, он спрашивает, есть ли способ предотвратить "скрытие" или нет.И простой ответ заключается в том, что "его нет!".

Вот еще раз его пример

Родительский класс определяет функцию:

int foo() { return 1; }

Дочерний класс, наследующий Родительский, снова определяет ту же функцию (не переопределяя):

int foo() { return 2; }

Вы можете сделать это на всех языках программирования.Нет ничего, что могло бы помешать компиляции этого кода (кроме настройки в компиляторе).Лучшее, что вы получите, - это предупреждение о том, что вы скрываете родительский метод.Если вы вызовете дочерний класс и вызовете метод foo, вы получите 2.Вы практически взломали код.

Это то, о чем он спрашивает.

предупреждение во время компиляции о скрытии невиртуальной унаследованной функции X.

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

Я думаю, то , о чем предупреждает вас компилятор , скрывается !!Действительно ли это переопределяется ?

компилятор может выдать вам предупреждение, но во время выполнения метод родительского класса будет вызван, если указатель имеет тип parent class , независимо от фактического типа объекта, на который он указывает.

Это интересно.Попробуйте создать небольшую автономную тестовую программу для вашего компилятора.

Я искал то же самое и вчера наткнулся на этот [довольно старый] вопрос.

Сегодня я нашел отличное ключевое слово для c ++ 11 : final .Я подумал, что это может быть полезно следующим читателям.

http://en.cppreference.com/w/cpp/language/final

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

т. е.:

Parent* obj = new Child();

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

Итак, по умолчанию C ++ делает то, что вы хотите.

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

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

В вашем примере ни одна функция не переопределяется.Вместо этого он скрыт (это своего рода вырожденный случай перегрузки).Ошибка находится в коде дочернего класса.Как предложил csmba, все, что вы можете сделать, это изменить настройки вашего компилятора (если это возможно). ;все должно быть в порядке до тех пор, пока вы не используете стороннюю библиотеку, которая скрывает свои собственные функции.

Технически вы можете предотвратить переопределение виртуальных функций.Но вы никогда больше не сможете ничего изменить или добавить.Это не полная помощь.Лучше использовать комментарий перед функцией, как предлагает faq lite.

Методы C ++ по умолчанию являются закрытыми и не переопределяемыми.

  • Вы не можете переопределить закрытый метод
  • Вы не можете переопределить не-virtual способ

Возможно, вы имеете в виду перегрузку?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top