Здравствуйте, so5team, Вы писали:
S>>>Предлагаю посмотреть на свой код, на исходный и сравнить сигнатуры виртуальных методов f и vf. В исходном примере сигнатуры одинаковые, в вашем -- нет. BFE>>Сигнатуры f одинаковые. S>f в вашем примере не виртуальная функция. Т.е. это не эквивалент ни разу.
Так в этом и состоит "ошибка" исходного примера: если потомок не должен наследовать поведение, то функция не должна быть виртуальной.
S>Ваш пример показывает то, что если в языке напрямую нельзя сделать требуемое, то можно найти обходной маневр, усложнить логику и обложиться обертками. Но все это лишь демонстрирует недостаточный уровень поддержки ООП из-за чего обходной маневр с обертками и нужен.
Не согласен. Приведённый пример может демонстрировать три различных проблемы:
1) ошибка в дизайне иерархии: метод который не должен наследоваться объявлен виртуальным;
2) ошибка в дизайне класса D: вместо композиции/агрегации использовано наследование;
3) пересечение по именам в названии наследуемого метода (это когда методы делают совершенно разное, но совпали по именам)
1) Первый случай очень редкий. Очень редко но бывает, что метод совпадает по имени и сигнатуре, но не наследуется. Такое может быть, если наследование не public.
2) Второй случай самый распространённый. Бывает сложно отличить владение объектом в единственном экземпляре от наследования от этого объекта. Для различения следует использовать эвристический приём: если класс B может хотя бы теоретически (даже если в коде такого нет и никогда не будет) иметь два объекта класса A, то должна быть композиция/агрегация, а не наследование. (Автомобиль можно отнаследовать от мотора, но — нет, так делать не надо. Поток можно отнаследовать от буфера — у обоих есть схожие методы put, flush, но так как у потока теоретически может быть несколько буферов или не быть его вовсе, то это не отношение наследования).
3) Пересечение по именам не связано с ООП и может происходить (и происходит) в других языках, без ООП.