覆盖方法时 virtual 关键字是啥意思?
Posted
技术标签:
【中文标题】覆盖方法时 virtual 关键字是啥意思?【英文标题】:What does the virtual keyword mean when overriding a method?覆盖方法时 virtual 关键字是什么意思? 【发布时间】:2011-06-18 16:31:10 【问题描述】:virtual 关键字在重写方法时有什么作用?我没有使用它,一切正常。
每个编译器在这方面的行为是否相同?
我应该使用它还是不使用它?
【问题讨论】:
C++ Virtual/Pure Virtual Explained 的可能重复项 @Harald:不。不同的主题。 但我问的是该关键字的用法。与抽象虚拟方法无关。 派生类中的虚拟关键字是可选的,但最好跳过它。否则,如果您有很多派生类,并且想要将继承的方法之一设为虚拟,则必须在所有这些派生类中为该方法添加 virtual 关键字。 【参考方案1】:没有它,您无法覆盖成员函数。
你只能隐藏一个。
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
——你的对象是多态的。
(由于the slicing problem,您还必须为此使用引用或指针。)
Derived::foo
不需要重复 virtual
关键字,因为 Base::foo
已经使用了它。这是由标准保证的,您可以依赖它。不过,为了清楚起见,有些人认为最好保留这一点。
【讨论】:
我知道在声明可以被覆盖的方法时 virtual 是必要的。我问过在覆盖方法时使用这个关键字,而不是声明。 @Miro:我不关注。您通过声明另一个覆盖它的函数来覆盖它。不管怎样,至少我的最后一段回答了你的问题。【参考方案2】:基类中的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
。
【讨论】:
【参考方案3】:当一个函数是虚拟的时,它在整个层次结构中都保持虚拟,无论您是否每次都明确指定它是虚拟的。覆盖方法时,使用 virtual 以更明确 - 没有其他区别:)
class A
virtual void f()
/*...*/
;
;
class B:public A;
virtual void f() //same as just void f()
/*...*/
;
;
【讨论】:
【参考方案4】:Extending on Light Races answer,也许这会帮助一些人看看它在做什么。
struct Base
public:
void foo()
printf_s("Base::foo\n");
;
struct Derived : Base
void foo()
printf_s("Derived::foo\n");
;
struct BaseVirtual
public:
virtual void foo()
printf_s("BaseVirtual::foo\n");
;
struct DerivedVirtual : BaseVirtual
virtual void foo()
printf_s("DerivedVirtual::foo\n");
;
Derived d;
d.foo(); // Outputs: Derived::foo
Base& b = d;
b.foo(); // Outputs: Base::foo
DerivedVirtual d2;
d2.foo(); // Outputs: DerivedVirtual::foo
BaseVirtual& b2 = d2;
b2.foo(); // Outputs: DerivedVirtual::foo
【讨论】:
以上是关于覆盖方法时 virtual 关键字是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章