Что делает ключевое слово virtual при переопределении метода? Я не использую его, и все работает нормально.
Поддерживает ли каждый компилятор одинаковый в этом отношении?
Должен ли я использовать его или нет?
Что делает ключевое слово virtual при переопределении метода? Я не использую его, и все работает нормально.
Поддерживает ли каждый компилятор одинаковый в этом отношении?
Должен ли я использовать его или нет?
Вы не можете переопределить функцию-член без нее.
Вы можете только скрыть его.
struct Base {
void foo() {}
};
struct Derived : Base {
void foo() {}
};
Derived::foo
не отменяет Base::foo
; он просто скрывает его, потому что он имеет то же имя, что и следующее:
Derived d;
d.foo();
вызывает Derived::foo
.
virtual
позволяет полиморфизм таким образом, чтобы вы фактически переопределяли функции:
struct Base {
virtual void foo() {}
};
struct Derived : Base {
virtual void foo() {} // * second `virtual` is optional, but clearest
};
Derived d;
Base& b = d;
b.foo();
Это вызывает Derived::foo
, потому что теперь это переопределяет Base::foo
— ваш объект является полиморфным.
(Вы также должны использовать для этого ссылки или указатели, из-за проблема среза.
Derived::foo
не нужно повторять ключевое слово virtual
, потому что Base::foo
уже использовал его. Это гарантируется стандартом, и вы можете положиться на него. Однако некоторые считают, что лучше всего сохранить это для ясности.Метод A virtual
в базовом классе будет каскадироваться через иерархию, делая каждый метод подкласса с той же сигнатурой также virtual
.
class Base{
public:
virtual void foo(){}
};
class Derived1 : public Base{
public:
virtual void foo(){} // fine, but 'virtual' is no needed
};
class Derived2 : public Base{
public:
void foo(){} // also fine, implicitly 'virtual'
};
Я бы рекомендовал писать virtual
, хотя, если только для целей документации.
Когда функция виртуальна, она остается виртуальной по всей иерархии, независимо от того, явно ли вы указываете каждый раз, когда она виртуальна. При переопределении метода используйте виртуальный, чтобы быть более явным - никакой другой разницы:)
class A
{
virtual void f()
{
/*...*/
};
};
class B:public A;
{
virtual void f() //same as just void f()
{
/*...*/
};
};