Есть ли способ предотвратить переопределение метода в подклассах? - PullRequest
27 голосов
/ 20 августа 2008

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

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

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

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

Ответы [ 14 ]

33 голосов
/ 04 июня 2013

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

12 голосов
/ 20 августа 2008

Пара идей:

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

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

Удачи!

6 голосов
/ 20 августа 2008

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

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

2 голосов
/ 13 октября 2009

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

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

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

int foo() { return 1; }

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

int foo() { return 2; }

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

Это то, что он просит.

2 голосов
/ 23 сентября 2008

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

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

1 голос
/ 04 августа 2016

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

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

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

1 голос
/ 23 сентября 2008

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

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

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

1 голос
/ 20 августа 2008

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

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

0 голосов
/ 12 декабря 2009

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

0 голосов
/ 23 сентября 2008

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

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