- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
#include <iostream>
class Base {
public:
void publicThingy() const {
std::cout << "Base::publicThingy()\n";
privateThingy();
}
private:
virtual void privateThingy() const {
std::cout << "Base::privateThingy()\n";
}
};
class Derived : public Base {
private:
virtual void privateThingy() const {
std::cout << "Derived::privateThingy()\n";
}
};
int main() {
const Base &b = Derived();
b.publicThingy();
}
Для любителей покритиковать костыли в крестах. Еще один повод: vtable'y до лампочки на private/public.
https://wandbox.org/permlink/tAjx2MKozsbJ8QyT
Elvenfighter 29.03.2017 17:58 # 0
Dummy00001 30.03.2017 11:32 # +1
> Еще один повод: vtable'y до лампочки на private/public.
публик/приват это только для разрабов - на митингах громко полаятся, или в вершн контрол тихие войны вести. на кодогенерацию/рантайм/этц имеет почти нулевой эффект.
Elvenfighter 01.04.2017 06:51 # 0
roman-kashitsyn 29.03.2017 18:35 # +4
Elvenfighter 30.03.2017 07:08 # 0
Antervis 30.03.2017 08:54 # 0
п.с. private virtual всё-таки что-то из разряда "не надо так"
roman-kashitsyn 30.03.2017 09:22 # 0
Пишем на плюсах, а мейерса не читали, как так? Я всё время использую NVI.
private управляет доступом, а не возможностью переопределять. Т.е. приватную виртуальную функцию переопределить можно, а вызвать -- нет. Это же киллер-фича, потому-что унылый protected толком ничего не скрывает.
Antervis 30.03.2017 10:18 # 0
А это так называемый fragile interface
roman-kashitsyn 30.03.2017 12:01 # 0
Да, но не совсем так: можно переопределить И сделать публичным, просто опубликовать кишки базового класса нельзя. Тут уж пусть наследник пусть сам свои кишки защищает.
С другой стороны да, если уж хочется прострелить себе ногу, способ всегда найдётся.
Antervis 30.03.2017 12:09 # 0
нельзя. Хотя, при определении методов очень часто надо вызвать базовую реализацию. Поэтому опять же, NVI хрупок, а виртуальные методы лучше делать в public/protected
roman-kashitsyn 30.03.2017 13:16 # 0
А вот и нет, NVI отчасти нужен для того, чтобы нельзя было забыть это сделать. Трёхуровневые иерархии нинужны.
Antervis 30.03.2017 19:46 # 0
Desktop 09.09.2018 16:48 # 0
firefred 09.09.2018 23:30 # 0
Dummy00001 30.03.2017 11:53 # 0
я не уловил в чем фишка. там два обзаца из какой произвольной "ОО для чайников" слизано - и потом это названо паттерном.
roman-kashitsyn 30.03.2017 12:12 # +2
Суть в том, чтобы считать наличие виртуальных функций скорее деталью реализации, чем частью интерфейса. Делаешь все публичные методы невиртуальными, все виртуальные — приватными. Так можно легко добавлять в базовый класс код, который должен быть общим для всех "потомков". Например: Так потомки не смогут забыть проверить данные и инициализировать базовый класс.
> http://www.blackwasp.co.uk/NVI.aspx
Лучше http://www.gotw.ca/publications/mill18.htm
Dummy00001 30.03.2017 13:01 # 0
на крестах, с его static binding, интерфейсы всегда были граблями обложены. (к слову, object slicing было первое что я подумал когда код в ГК увидел.) но как стандарт развивается, даже какой примитивной встроенной версии run-time binding или мессадж диспатч мы в крестах никогда недождёмся. на потомках smalltalk'а (за исключением жабы) проблем с интерфейсами редко наблюдается, т.к. интерфейсы слабые (более duck typing, чем компайл тайм чекинг), их проще менять в ходе жизни проекта, потому что нет такой жесткой привязки подклассов к базовому классу.
Psionic 30.03.2017 12:16 # 0