Вопрос в теме предполагает довольно распространенное замешательство. Путаница достаточно распространена, что C++ FAQ долгое время выступал против использования частных виртуальных программ, потому что путаница, казалось, была плохой.
Итак, чтобы сначала избавиться от путаницы: Да, частные производные функции могут быть переопределены в производных классах. Методы производных классов не могут вызывать виртуальные функции из базового класса, но они могут обеспечить им собственную реализацию. Согласно Herb Sutter, наличие публичного не виртуального интерфейса в базовом классе и частная реализация, которые могут быть настроены в производных классах, позволяет лучше «отделять спецификацию интерфейса от спецификации настраиваемого поведения реализации». Вы можете прочитать об этом в своей статье "Virtuality".
Есть, однако, еще одна интересная вещь в коде, который вы представили, что, на мой взгляд, заслуживает большего внимания. Открытый интерфейс состоит из набора перегруженных не виртуальных функций, и эти функции вызывают непубличные, не перегруженные виртуальные функции. Как обычно в мире C++ это идиома, у нее есть имя и, конечно, полезно. Имя (сюрприз, сюрприз!)
"Открытый перегружен Non-Virtuals вызовов Защищенные не перегруженный виртуалов"
Это помогает properly manage the hiding rule. Вы можете узнать больше об этом here, но я попытаюсь объяснить это в ближайшее время.
Представьте, что виртуальные функции класса Engine
также являются его интерфейсом, и это набор перегруженных функций, которые не являются чистыми виртуальными. Если бы они были чистыми виртуальными, то все же можно было столкнуться с одной и той же проблемой, как описано ниже, но ниже в иерархии классов.
class Engine
{
public:
virtual void SetState(int var, bool val) {/*some implementation*/}
virtual void SetState(int var, int val) {/*some implementation*/}
};
Теперь давайте предположим, что вы хотите создать производный класс, и вам необходимо обеспечить новую реализацию только для метода, который принимает два целых в качестве аргументов.
class MyTurbochargedV8 : public Engine
{
public:
// To prevent SetState(int var, bool val) from the base class,
// from being hidden by the new implementation of the other overload (below),
// you have to put using declaration in the derived class
using Engine::SetState;
void SetState(int var, int val) {/*new implementation*/}
};
Если вы забыли поставить, используя декларацию в производном классе (или переопределить вторую перегрузку), вы можете попасть в беду в приведенном ниже сценарии.
MyTurbochargedV8* myV8 = new MyTurbochargedV8();
myV8->SetState(5, true);
Если вы не допустить скрытие Engine
членов, утверждение:
myV8->SetState(5, true);
назвал бы void SetState(int var, int val)
из производного класса, преобразования true
в int
.
Если интерфейс не является виртуальным и виртуальная реализация непубличный, как в вашем exmaple, автор производного класса имеет один меньше проблемы думать о и может просто написать
class MyTurbochargedV8 : public Engine
{
private:
void SetStateInt(int var, int val) {/*new implementation*/}
};
+1 для «Public Overloaded Non-Virtuals Call Protected Non-Overloaded Virtuals» xD – GabLeRoux
Почему виртуальная функция должна быть частной? Можно ли это публично? – Rich
Интересно, сохраняются ли сегодня рекомендации, данные Хербом Саттером в его статье «Виртуальность»? – nurabha