当前位置: 首页 > 知识库问答 >
问题:

我应该使用虚拟,覆盖,还是两个关键字都用?

阎烨
2023-03-14

在过去的几周里,有一些关于< code>virtual和< code>override的事情困扰着我的大脑。我了解到,当你用虚函数做继承时,你必须添加< code>virtual来让编译器知道搜索正确的函数。后来我还了解到在c 11中有一个新的关键字- override。现在我有点迷茫;我需要在程序中同时使用虚拟关键字和重写关键字吗,或者最好只使用其中一个?

解释我自己-我的意思的代码示例:

class Base
{
public:
    virtual void print() const = 0;
    virtual void printthat() const = 0;
    virtual void printit() const = 0;
};

class inhert : public Base
{
public:
    // only virtual keyword for overriding.
    virtual void print() const {}

    // only override keyword for overriding.
    void printthat() const override {}

    // using both virtual and override keywords for overriding.
    virtual void printit() const override {}
};

最好的方法是什么?

共有2个答案

夏华藏
2023-03-14

根据C核心指南C.128,每个虚拟函数声明都应指定virtualoverridefinal中的一个。

  • virtual:用于基类中函数的“第一次”出现
  • <code>override</code>:对于从提供相同(或协变)签名的<code>virtual</code>函数的某个基类派生的类中的<code<virtual</code>函数的重写</li>
  • final:用于将覆盖标记为不可覆盖。也就是说,具有最终虚拟函数重写的类的派生不能重写该虚拟函数重写
struct A {
    virtual void go() { puts("A"); }
};
struct B : A {
    // Overrides A::go(). No need to specify `virtual` explicitly,
    // it already implicitly is virtual and overrideable
    void go() override { puts("B"); }
};
struct C : B {
    void go() final { puts("C"); }
    //virtual void go() override final { puts("C"); } would still compile,
    // but it is considered, for lack of a better description, "extra"
};
struct D : C {
    // Would produce error C3248 : 'C::go' : function declared as 'final' cannot be overridden by 'D::go'
    //void go() override { puts("D"); }
};
曾嘉福
2023-03-14

重写函数时,技术上不需要编写virtualoverride

原始基类声明需要关键字虚拟将其标记为虚拟。

在派生类中,通过与基类函数具有¹相同的类型,该函数是虚拟的。

然而,当预期的重写在技术上不是重写时,重写可以通过生成编译错误来帮助避免错误。例如,函数类型与基类函数不完全相同。或者基类的维护更改了函数的类型,例如添加默认参数。

同样,派生类中的 virtual 关键字可以通过确保函数在进一步的派生类中仍然是虚拟的,使此类错误更加微妙。

所以一般的建议是,

>

  • virtual 用于基类函数声明。
    这在技术上是必要的。

    对派生类的重写使用override(仅限)
    这有助于维护。

    示例:

    struct Base { virtual void foo() {} };
    struct Derived: Base { void foo() override {} };
    

    注意:
    ¹ C 支持协变原始指针和原始引用结果。对于协方差,覆盖的类型并不完全相同。它只有一个兼容的类型。

  •  类似资料:
    • 是否真的有必要使用或? 我知道在这个总的话题上有很多问题,例如: 派生类中函数的“virtual”关键字。有必要吗? < Li >“override”关键字是否只是对被重写的虚方法的检查? < li >虚拟?覆盖?还是两者都有?C 从这些和其他标记为重复项的内容中(许多“重复项”的答案都包含至少对我来说是新的不同信息),我学到了一些东西(我认为,大致为什么它们是真的):没有虚拟的覆盖不会编译。没有

    • 我想知道为什么我们不应该重写非虚拟函数?

    • 在C语言中对一个函数同时使用< code>virtual和< code>override有危险吗?这会让你对重载产生歧义吗? 显然,必须在基类中使用,在派生类中不使用是很愚蠢的,但在派生类中将与一起使用实际上有问题吗? 试图确定这是一个风格还是正确性的问题。 例子:

    • 据我所知,在C 11中引入<code>override</code>关键字只不过是一种检查,以确保正在实现的函数是基类中<code>虚拟</code>函数的<code>override</code>ing。 是这样吗?

    • 问题内容: 我有一个只包含字段而没有方法的类,如下所示: 这可以很容易地翻译成字典。该类对于将来的添加更加灵活,使用可以更快。那么使用dict会有好处吗?字典会比全班更快吗?并且比具有插槽的课程快吗? 问题答案: 你为什么要把它当作字典?有什么好处?如果您以后要添加一些代码,会发生什么?您的代码会去哪儿? 类用于捆绑相关数据(通常是代码)。 字典用于存储键- 值关系,其中通常键都是同一类型,并且所

    • 问题内容: 我正在使用c / c 为osx和linux开发命令行界面可执行文件。该项目将链接到opencv。我应该使用libc 还是libstdc ++? 问题答案: 我会为每个操作系统使用本机库,即GNU / Linux上的libstdc 和Mac OS X上的libc 。 libc 在GNU / Linux上不是100%完整的,而libstdc 更完整时使用libc并没有真正的优势。另外,如果