Во-первых, плохие новости заключаются в том, что вы не можете переопределить или скрыть виртуальную функцию с помощью другой функции, которая отличается только типом возврата. Еще одна плохая новость: C ++ дает вам достаточно веревки, чтобы повеситься во многих отношениях, которые вы раньше не рассматривали, и вы можете получить аналогичный эффект:
struct base {
virtual std::string const & f() {
static std::string s = "virtual";
return s;
}
};
namespace detail {
class place_holder; // no need to define it, it is just a place holder (duh)
}
struct derived : public base {
std::string f( place_holder* p = 0 ) { return "crooked"; }
};
int main() {
derived d; std::cout << d.f() << std::endl; // crooked
base& b = d; std::cout << b.f() << std::endl; // virtual
}
Хитрость в том, что, определяя метод с тем же именем и разными аргументами в производном классе, вы фактически скрываете базовый класс (если вы не добавите using base::f
в производный класс, но тогда вызов будет неоднозначным) , В то же время, поскольку единственный добавленный аргумент имеет значение по умолчанию, вы можете вызывать его без аргументов, и компилятор добавит аргумент по умолчанию для вас.
Обратите внимание, что вы на самом деле не удаляете метод из объекта, а скорее скрываете его в производном классе. Если метод вызывается через указатель или ссылку на базовый класс, виртуальный метод все еще существует и будет вызван.