简体   繁体   English

`final`的食谱:省略`virtual`?

[英]Recipe for `final`: omit `virtual`?

Is it a valid recipe to say that if I write final (to a member function) one should not write virtual ? 这是一个有效的方法,如果我写final (成员函数),不应该写virtual

In a base class, final methods would make no sense: 在基类中, final方法没有意义:

struct Driver {
    virtual void print();
};

If one would add final to print() this would defy the reason for polymorphism in the first place. 如果要将final添加到print()这将首先违反多态性的原因。 So that would be useless (though possible). 所以这将是无用的(虽然可能)。

When I derive from this class I can detect errors with final , but only without virtual : 当我从这个类派生时,我可以 final检测错误,但只有没有 virtual

struct KeyboardDriver : public Driver {
    virtual void prynt() final;    // Oops: typo, but compiler-ok
};

struct MouseDriver : public Driver {
    void prynt() final;    // Error: Hooray, compiler found my typo
};

The additional final for KeyboardDriver::prynt was legal. KeyboardDriver::prynt的额外final是合法的。 Because final only requires the member function to be virtual -- the compiler lets this pass (FDIS 9.2p9). 因为final只需要成员函数是virtual - 编译器允许它通过(FDIS 9.2p9)。

But when I leave out the virtual the typo makes this function non-virtual -- it overrides nothing, ie no virtual function. 但是当我忽略virtual ,拼写错误使得这个函数非虚拟 - 它不会覆盖任何东西,即没有虚函数。 Therefore final without virtual serves the same purpose to this respect as override does. 因此,没有virtual final就像override一样在这方面起到了相同的作用。

Update: Is my analysis correct? 更新: 我的分析是否正确? Does the functionality of final without virtual include that one of override ? 没有virtualfinal的功能是否包含override

That is not what final is for. 这不是final的结果。 What you are looking for is override . 您正在寻找的是override

struct Base { 
  virtual void print();
};

struct Derived : Base {
  void prynt() override; //compiler error
};

struct Good : Base {
  void print() override; //no compiler error
};

If you mark a function as override when it does not, then you get an error. 如果将函数标记为override ,则不会,则会出现错误。 Combined with your final function, you get all the comforts of compiler checked safety, with the clarity of explicitly marking functions virtual when coding standards demand it. 与您的最终功能相结合,你的编译器的所有舒适安全检查,以明确地标记功能清晰度virtual时编码标准所要求的。

struct Best : Base {
  virtual void print() final override;
};

Your analysis is correct. 你的分析是正确的。 Not marking a final member as virtual avoids declaring a new, non-overriden member and catches mistakes. 不将final成员标记为virtual成员可以避免声明新的非重写成员并捕获错误。 However, since that's the purpose of override , it may be simpler to just use final override ; 但是,由于这是override的目的,因此使用final override可能更简单; then whether the member is marked virtual or not won't matter at all. 那么该成员是否被标记为virtual将无关紧要。

I do not think it is an error, it's just a virtual function that can not be overloaded. 我不认为这是一个错误,它只是一个无法重载的虚函数。 Same thing that would happen if the function were declared virtual in a parent class, since virtual declarations are inherited. 如果函数在父类中声明为虚拟,则会发生同样的事情,因为虚拟声明是继承的。 It would make no sense to forbid it. 禁止它是没有意义的。

Is my analysis correct? 我的分析是否正确? Does the functionality of final without virtual include that one of override? 没有虚拟的final的功能是否包含覆盖的功能?

No. The reason that this was a compiler error: 不。这是编译器错误的原因:

void prynt() final;    // Error: Hooray, compiler found my typo

Is because final is only allowed on virtual functions. 是因为final只允许在函数上使用。 The compiler is complaining because you used it on a function that isn't virtual. 编译器抱怨,因为你在一个非虚拟的函数上使用它。

There is nothing syntactically wrong about this line: 这条线在语法上没有任何错误:

virtual void prynt() final;    // Oops: typo, but compiler-ok

It may not be what you want, but this is legitimate (and even meaningful, depending on the circumstances) code. 它可能不是你想要的,但这是合法的(甚至是有意义的,取决于具体情况)代码。

The problem you are encountering is due to wanting to do this: 您遇到的问题是由于想要这样做:

struct Driver {
    virtual void print();
};
struct MouseDriver : public Driver {
    void print();
};

Omitting the virtual is technically legal. 省略virtual技术在技术上是合法的。 But personally, I've always felt that it was bad form. 但就个人而言,我一直觉得这是糟糕的形式。 You're putting vital information (which functions are overridden) into another class. 您将重要信息(被覆盖的功能)放入另一个类中。 I think it was a mistake to even allow this to compile. 我认为甚至允许这个编译是错误的。

If you want to avoid this problem, then explicitly state virtual on all virtual functions, and use override in the places where you mean to create a new function. 如果要避免此问题,请在所有虚函数上显式声明virtual ,并在创建新函数的位置使用override Then, this will fail to compile correctly. 然后,这将无法正确编译。

struct Driver {
    virtual void print();
};
struct MouseDriver : public Driver {
    virtual void print() override;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM