26
votes

I've been having a discussion with my coworkers as to whether to prefix overridden methods with the virtual keyword, or only at the originating base class.

I tend to prefix all virtual methods (that is, methods involving a vtable lookup) with the virtual keyword. My rationale is threefold:

  1. Given that C++ lacks an override keyword, the presence of the virtual keyword at least notifies you that the method involves a lookup and could theoretically be overridden by further specializations, or could be called through a pointer to a higher base class.

  2. Consistently using this style means that, when you see a method (at least within our code) without the virtual keyword, you can initially assume that it is neither derived from a base nor specialized in subclass.

  3. If, through some error, the virtual were removed from IFoo, all children will still function (CFooSpecialization::DoBar would still override CFooBase::DoBar, rather than simply hiding it).

The argument against the practice, as I understood it, was, "But that method isn't virtual" (which I believe is invalid, and borne from a misunderstanding of virtuality), and "When I see the virtual keyword, I expect that means someone is deriving from it, and go searching for them."

The hypothetical classes may be spread across several files, and there are several specializations.

class IFoo {
public:
    virtual void DoBar() = 0;
    void DoBaz();
};

class CFooBase : public IFoo {
public:
    virtual void DoBar(); // Default implementation
    void DoZap();
};


class CFooSpecialization : public CFooBase {
public:
    virtual void DoBar(); // Specialized implementation
};

Stylistically, would you remove the virtual keyword from the two derived classes? If so, why? What are Stack Overflow's thoughts here?

6
I'd be interested to see Bjarne's (or the C++ committee's) rationale for why virtual is even allowed to be omitted in the derived class. The rationale might provide more compelling reasons for actually omitting it than does your colleague. Perhaps only in certain cases, though.Steve Jessop
Unfortunately there is no rationale included in the spec. It just says it is "legal but redundant (has empty semantics)". Would be interesting to hear, though, if there is any record of what the rationale was.Tyler McHenry
I don't have a copy of "design and evolution", which may or may not contain anything about it.Steve Jessop
I'd like to point out that as of C++11, you can also use the override specifier to, well, specify that a function is virtual and overrides another function; doing so also allows the compiler to give you an error message if the function doesn't override anything. With your example, CFooBase and CFooSpecialization would have virtual void DoBar() override;.Justin Time - Reinstate Monica
@JustinTime I think what people want, as impractical as it is, is a Standard-enforced way to require descriptive vfunc declarations, rather than having to remember to deliberately type yet another keyword that is totally optional without having to turn on compiler-dependent warnings. But I think it's too late for that now in terms of what it'd break and the customary backlash that would result. That said, here's the trick for g++: stackoverflow.com/questions/29145476/…underscore_d

6 Answers

23
votes

I completely agree with your rationale. It's a good reminder that the method will have dynamic dispatch semantics when called. The "that method isn't virtual" argument that you co-worker is using is completely bogus. He's mixed up the concepts of virtual and pure-virtual.

6
votes

A function once a virtual always a virtual.

So in any event if the virtual keyword is not used in the subsequent classes, it does not prevent the function/method from being 'virtual' i.e. be overridden. So one of the projects that I worked-in, had the following guideline which I somewhat liked :

  • If the function/method is supposed to be overridden always use the 'virtual' keyword. This is especially true when used in interface / base classes.
  • If the derived class is supposed to be sub-classed further explicity state the 'virtual' keyword for every function/method that can be overridden. C++11 use the 'override' keyword
  • If the function/method in the derived class is not supposed to be sub-classed again, then the keyword 'virtual' is to be commented indicating that the function/method was overridden but there are no further classes that override it again. This ofcourse does not prevent someone from overriding in the derived class unless the class is made final (non-derivable), but it indicates that the method is not supposed to be overridden. Ex: /*virtual*/ void guiFocusEvent(); C++11, use the 'final' keyword along with the 'override' Ex: void guiFocusEvent() override final;
4
votes

Adding virtual does not have a significant impact either way. I tend to prefer it but it's really a subjective issue. However, if you make sure to use the override and sealed keywords in Visual C++, you'll gain a significant improvement in ability to catch errors at compile time.

I include the following lines in my PCH:

#if _MSC_VER >= 1400
#define OVERRIDE override
#define SEALED sealed
#else
#define OVERRIDE
#define SEALED
#endif
3
votes

I would tend not to use any syntax that the compiler will allow me to omit. Having said that, part of the design of C# (in an attempt to improve over C++) was to require overrides of virtual methods to be labeled as "override", and that seems to be a reasonable idea. My concern is that, since it's completely optional, it's only a matter of time before someone omits it, and by then you'll have gotten into the habit of expecting overrides to be have "virtual" specified. Maybe it's best to just live within the limitations of the language, then.

0
votes

I can think of one disadvantage: When a class member function is not overridden and you declare it virtual, you add an uneccessary entry in the virtual table for that class definition.

0
votes

Note: My answer regards C++03 which some of us are still stuck with. C++11 has the override and final keywords as @JustinTime suggests in the comments which should probably be used instead of the following suggestion.

There are plenty of answers already and two contrary opinions that stand out the most. I want to combine what @280Z28 mentioned in his answer with @StevenSudit's opinion and @Abhay's style guidelines.

I disagree with @280Z28 and wouldn't use Microsoft's language extensions unless you are certain that you will only ever use that code on Windows.

But I do like the keywords. So why not just use a #define-d keyword addition for clarity?

#define OVERRIDE
#define SEALED

or

#define OVERRIDE virtual
#define SEALED virtual

The difference being your decision on what you want to happen in the case you outline in your 3rd point.

3 - If, through some error, the virtual were removed from IFoo, all children will still function (CFooSpecialization::DoBar would still override CFooBase::DoBar, rather than simply hiding it).

Though I would argue that it is a programming error so there is no "fix" and you probably shouldn't even bother mitigating it but should ensure it crashes or notifies the programmer in some other way (though I can't think of one right now).

Should you chose the first option and don't like adding #define's then you can just use comments like:

/* override */
/* sealed */

And that should do the job for all cases where you want clarity, because I don't consider the word virtual to be clear enough for what you want it to do.