Why is 'virtual' optional for overridden methods in derived classes?

前端 未结 5 1813
走了就别回头了
走了就别回头了 2021-02-05 12:53

When a method is declared as virtual in a class, its overrides in derived classes are automatically considered virtual as well, and the C++ language ma

相关标签:
5条回答
  • 2021-02-05 13:25

    Weak point in design, I agree. I also think that'd be really nice if there was a different syntax for two different things:

    1. Declaring a virtual function. I.e. the function that may be overridden in derived class. (This thing actually adds a new function entry in the vtable.)
    2. Overriding a virtual function in the derived class.

    With current C++ rules when overriding a function - it's easy to screw things. If you mistype the function name (or make a mistake in its parameters list) - then you actually do (1) instead of (2).

    And you have no error/warning. Just get the surprise at run-time.

    0 讨论(0)
  • 2021-02-05 13:28

    As a related note, in C++0x you have the option of enforcing being explicit with your overrides via the new attribute syntax.

    struct Base {
      virtual void Virtual();
      void NonVirtual();
    };
    
    struct Derived [[base_check]] : Base {
      //void Virtual(); //Error; didn't specify that you were overriding
      void Virtual [[override]](); //Not an error
      //void NonVirtual [[override]](); //Error; not virtual in Base
      //virtual void SomeRandomFunction [[override]](); //Error, doesn't exist in Base
    };
    

    You can also specify when you intend to hide a member via the [[hiding]] attribute. It makes your code somewhat more verbose, but it can catch a lot of annoying bugs at compile time, like if you did void Vritual() instead of void Virtual() and ended up introducing a whole new function when you meant to override an existing one.

    0 讨论(0)
  • 2021-02-05 13:32

    That is a good question, and I certainly agree that it is good style to redeclare a method virtual in the derived class if it has been declared virtual in the base class. While there are some languages that build style into the language (e.g. Google Go and, to some extent, Python), C++ is not one of those languages. While it certainly is possible for a compiler to detect that a derived class does not reuse the keyword "virtual" for something declared "virtual" in a base class (or, more importantly, that the derived class declares a function of the same name as the base class and it has not been declared virtual in the base class), there are, in fact, settings on many compilers to issue warnings (and even error messages) in the event that this happens. At this stage, though, it would not be practical to institute such a requirement in the language as there exists too much code that is not that strict. Moreover, developers can always choose to be more stringent than the language and can turn up compiler warning levels.

    0 讨论(0)
  • 2021-02-05 13:34

    Since the language can't enforce "good" style, C++ generally doesn't even try. At least IMO, it's open to question whether including redundant specifiers like this is good style in any case (personally, I hate when they're there).

    (At least parts of) Google's coding standards may make sense under some circumstances, but as far as C++ in general goes, are generally considered mediocre advice at best. To an extent, they even admit that -- some of them they openly state are only really there to fit with their old code. Other parts they don't admit so directly, and (to be entirely honest) that argument wouldn't support some of their standards anyway (i.e., some of it seems to lack real justification).

    0 讨论(0)
  • 2021-02-05 13:43

    Yeah, it would really be nicer to make the compiler enforce the virtual in this case, and I agree that this is a error in design that is maintained for backwards compatibility.

    However there's one trick that would be impossible without it:

    class NonVirtualBase {
      void func() {};
    };
    
    class VirtualBase {
      virtual void func() = 0;
    };
    
    template<typename VirtualChoice>
    class CompileTimeVirtualityChoice : public VirtualChoice {
      void func() {}
    };
    

    With the above we have compile time choice wether we want virtuality of func or not:

    CompileTimeVirtualityChoice<VirtualBase> -- func is virtual
    CompileTimeVirtualityChoice<NonVirtualBase> -- func is not virtual
    

    ... but agreed, it's a minor benefit for the cost of seeking a function's virtuality, and myself, I always try to type virtual everywhere where applicable.

    0 讨论(0)
提交回复
热议问题