Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

Несколько идей:

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

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

Удачи!

Ответ 2

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

При использовании в объявлении виртуальной функции 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.

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

Компилятор

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

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

Ответ 7

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

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

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

Ответ 8

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

т

Parent* obj = new Child();

Ответ 9

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

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

Ответ 10

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

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

Ответ 11

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

Ответ 12

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

Вот еще один пример:

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

int foo() { return 1; }

Класс Child, наследующий родительский элемент, определяет ту же функцию AGAIN (не переопределяя):

int foo() { return 2; }

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

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

Ответ 13

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

Ответ 14

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

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

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