Почему GoF советует использовать защищенные (в отличие от частных) виртуальные методы в реализации шаблона метода шаблона С++?
От банды четвертого по шаблону Метод:
Следует отметить три проблемы с реализацией:
- Использование контроля доступа С++. В С++ примитивные операции, которые вызывает метод шаблона, могут быть объявлены защищенными членами. Это обеспечивает что они вызываются только методом шаблона. Примитивные операции которые должны быть переопределены, объявляются чистыми виртуальными. Метод шаблона сама по себе не должна быть переопределена; поэтому вы можете сделать шаблон метод - функция, не относящаяся к элементу.
"Это гарантирует, что они вызываются только методом шаблона." не правда, не так ли? Так как примитивные методы (если некоторые из них являются виртуальными, а не виртуальными, например, например), также могут быть вызваны из производного класса. Не правда ли, что только объявление примитивных методов private гарантирует, что они вызываются только методом шаблона? Частные виртуальные примитивные методы могут затем быть реализованы (или переопределены) в подклассах, чтобы обеспечить специализированное поведение, которое требуется в алгоритме, определенном в методе шаблона в суперклассе.
См. "Виртуальность" от Herb Sutter:
http://www.gotw.ca/publications/mill18.htm
Где он утверждает, что:
Руководство № 2: Предпочтение делать виртуальные функции частными. Руководство № 3: Только если производным классам необходимо вызвать базовую реализацию виртуальную функцию, защитите виртуальную функцию.
Я не вижу никаких требований в шаблоне метода шаблона GoF для производных классов для вызова реализаций виртуальных функций базового класса, так почему же банда из четырех рекомендует защищать эти функции, а не частные?
Ответы
Ответ 1
Ответ довольно прост:
Шаблоны проектирования датируются с 1994 года. В это время С++ все еще сильно развивается на языке, который мы знаем сегодня - предыдущий стандарт был завершен в 1998 году! Компиляторы были ошибочными и не поддерживали важные функции, которые мы сейчас считаем само собой разумеющимися.
Но что более важно, многие вещи еще не были обнаружены (в частности, основными программистами). Возьмите шаблон метапрограммирования, все из которого только "наткнулось" на примерно в то же время.
Я очень подозреваю, что то же самое верно для частных виртуальных функций: GoF просто не знал, что это законный С++. Или, если это было, он не утвердился в качестве конвенции.
Фактически, большинство С++-кодов, которые считались "хорошими" в 1994 году, будут считаться чрезмерно сложными и подверженными ошибкам сегодня, даже без учета С++ 11.