重写方法时虚拟关键字的含义是什么?

时间:2011-06-18 16:31:10

标签: c++ virtual-functions

重写方法时关键字虚拟的作用是什么?我没有使用它,一切正常。

每个编译器在这方面的行为是否相同?

我应该使用它吗?

4 个答案:

答案 0 :(得分:10)

没有它就无法覆盖成员函数。

你只能隐藏一个。

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已使用过它。这是标准的保证,你可以信赖它。但是,有些人认为最好保持清晰。

答案 1 :(得分:8)

基类中的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,但仅限于文档目的。

答案 2 :(得分:6)

当一个函数是虚函数时,它在整个层次结构中保持虚拟,无论您是否每次都显式指定它。覆盖方法时,使用虚拟以便更明确 - 没有其他区别:)

class A
{
    virtual void f() 
    {
      /*...*/
    };
};

class B:public A;
{
    virtual void f()  //same as just void f()
    {
        /*...*/
    };
};

答案 3 :(得分:0)

扩展“轻量级比赛”的答案,也许这将有助于某些人了解它在做什么。

(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXX');