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

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

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

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

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

20.08.2008 06:50:32
14 ОТВЕТОВ
РЕШЕНИЕ

Пара идей:

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

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

Удачи!

14
20.08.2008 06:53:40
но тогда мы не можем вызвать этот метод из других классов. ?
anshulkatta 1.07.2014 08:35:00
Обратите внимание, что в finalC ++ 11 добавлен спецификатор: stackoverflow.com/a/16906116/1025391
moooeeeep 11.06.2015 14:56:11
@moooeeeep final в этом случае не работает: struct foo { void bar() final; };не разрешено C ++
Jean-Michaël Celerier 3.08.2018 12:34:33
@ Jean-MichaëlCelerier Да, вам нужно сделать его виртуальным, чтобы это работало.
moooeeeep 3.08.2018 19:25:01
@moooeeeep хорошо, да, но вопрос явно о не виртуальных функциях. Иногда вы не хотите (если, например, вам нужна совместимость с C API) виртуалов.
Jean-Michaël Celerier 4.08.2018 11:22:03

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

то есть:

Parent* obj = new Child();
0
20.08.2008 06:53:36

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

  • Вы не можете переопределить приватный метод
  • Вы не можете переопределить не- virtualметод

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

-2
20.08.2008 06:54:28
Мы можем переопределить частные виртуальные функции.
Luc Hermitte 23.09.2008 12:52:07

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

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

1
21.08.2008 01:20:21

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

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

0
20.08.2008 06:57:47

Звуки , как то , что вы ищете является эквивалентом Java языка конечного ключевого слова , которое предотвращает метод от того переопределены подкласса .

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

6
23.05.2017 12:00:24
finalКлючевое слово введено C ++ 11 ( en.cppreference.com/w/cpp/language/final ). Также посмотрите мой ответ здесь ( stackoverflow.com/a/16896559/1025391 ) для другого примера.
moooeeeep 3.06.2013 12:20:08
Хорошо, я этого не знал. Спасибо за ссылки!
Danny Whitt 11.06.2013 14:42:29

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

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

0
21.08.2008 01:27:11

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

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

2
23.09.2008 12:02:39

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

0
23.09.2008 13:00:30

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

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

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

1
23.09.2008 13:13:01

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

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

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

int foo() { return 1; }

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

int foo() { return 2; }

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

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

2
26.09.2011 00:50:04

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

0
11.12.2009 21:51:56

Когда вы можете использовать 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ключевое слово.

36
26.07.2017 18:35:15
я удалил виртуальный, и он показал мне ошибку с базовой функцией вызова ... окончательная работа только с виртуальными функциями?
AbhimanyuAryan 9.04.2015 22:25:38
@AbhimanyuAryan исправим finalработает только с виртуальными методами , так не распространяется на этот вопрос
j b 4.07.2019 08:13:05
И обратите внимание, что (по крайней мере, в Visual C ++), если вы помечаете метод const как final, ему нужен const final, а не final const.
tschumann 22.03.2020 05:11:24

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

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

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

1
4.08.2016 06:00:41