2008-08-20 2 views
22

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

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

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

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

ответ

12

Пара идей:

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

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

Удачи вам!

+1

, но мы не можем назвать этот метод другими классами. ? – anshulkatta 2014-07-01 08:35:00

+6

Обратите внимание, что существует спецификатор `final`, добавленный с C++ 11: http://stackoverflow.com/a/16906116/1025391 – moooeeeep 2015-06-11 14:56:11

0

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

т.е.

Parent* obj = new Child(); 
-1

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

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

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

+1

Мы можем переопределить частные виртуальные функции. – 2008-09-23 12:52:07

2

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

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

0

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

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

6

Похоже, что вы ищете, это эквивалент языка Java final ключевое слово, которое prevents a method from being overridden by a subclass.

Как others здесь есть suggested, вы действительно не можете предотвратить это. Кроме того, похоже, что это довольно frequently asked question.

+4

Ключевое слово `final` представлено C++ 11 (http://en.cppreference.com/w/cpp/language/final). Также посмотрите на мой ответ здесь (http://stackoverflow.com/a/16896559/1025391) для другого примера. – moooeeeep 2013-06-03 12:20:08

0

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

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

2

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

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

0

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

1

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

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

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

0

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

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

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

int foo() { return 1; } 

класс ребенка, наследуя родительский определяет ту же функцию РАЗ (не перекрывая):

int foo() { return 2; } 

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

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

0

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

28

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

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

1

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

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

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

Смежные вопросы