код начинает работать как ожидалось (т.е. выводится "derived").
Почему? Каким тут боком замешана функция-оператор? И что можно сделать, что бы выводилось "derived", при условии, что оператор убирать нельзя и в catch должен остаться базовый тип?
с catch проблем здесь нет, проблема в throw — исключение формируется из актуального типа выражения, а оно у тебя в случае с оператором — Base. Соответственно, объект исключения будет иметь тип Base и будет создан путем копирования (т.е. срезки) из твоего объекта Derived. В случае без оператора у тебя тип выражения — Derived, соответственно он и кидается.
Решение в данном случае — либо,если компилятор поддерживает ковариантные возвращаемые значения, в Derived добавить перекрытый оператор<<, возвращающий ссылку на Derived.
Второе решение — создавать объект динамически и кидать указатель на него, а в catch — убивать.
В этом случае не забудь про виртуальный деструктор (он 90% нужен, если ты занимаешься виртуальными функциями).
Но это — плохая практика, ибо, во-первых, исключение может быть поймано через catch(...), и тогда ты не сможешь очистить память, а во-вторых, операция выделения памяти сама может кинуть исключение и ловить и обрабатывать придется его вместо того, что тебе надо.
Так что перекрой оператор<< в Derived — это наилучшее решение.
Если компилятор позволит, конечно.
Дело в том, что throw выбрасывает объект, созданный исходя из статического типа опреранда (15.1/3). В случае с operator << статический тип — это Base, поэтому throw создает объект типа Base, при этом исходный объект типа Derived срезается. Во втором случае выражение имеет тип Derived, поэтому и выбрасывается объект типа Derived.
Простейшее решение в данном случае — использовать явный каст:
H>код начинает работать как ожидалось (т.е. выводится "derived").
H>Почему? Каким тут боком замешана функция-оператор? И что можно сделать, что бы выводилось "derived", при условии, что оператор убирать нельзя и в catch должен остаться базовый тип?
Перкрыть реализацию operator << в классе Derived .