Main Content

AUTOSAR C++14 Rule A10-3-1

Virtual function declaration shall contain exactly one of the three specifiers: (1) virtual, (2) override, (3) final

Since R2020a

Description

Rule Definition

Virtual function declaration shall contain exactly one of the three specifiers: (1) virtual, (2) override, (3) final.

Rationale

Virtual functions implement polymorphic behavior in a class hierarchy. Once you declare a function as virtual in a base class, all instances of the function with an identical parameter list in the derived classes override the base function implicitly. If you rely on this implicit action by the compiler for implementing polymorphic functions, it can lead to errors. For instance:

  • A function can become inadvertently virtual because its signature matches a virtual function in the base class.

  • A function can become inadvertently non-virtual because there are differences in the parameter list.

Implicitly declaring virtual functions can also make the code hard to read.

To avoid inadvertent errors and to enhance readability, use the specifiers virtual, override, or final to explicitly define virtual or overriding functions. Because using more than one of these specifiers in a declaration is either redundant or a source of error, use exactly one of these specifiers:

  • Only virtual to declare a new virtual function.

  • Only override to declare a non-final overriding function of a virtual function.

  • Only final to declare a final overriding function of a virtual function.

Polyspace Implementation

Polyspace® flags declaration of virtual functions if:

  • The declaration uses none of the specifiers.

  • The declaration uses more than one of the specifiers.

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#include<cstdint>
class Base
{
public:
	virtual void F() noexcept = 0;                 // Compliant
	virtual void G() noexcept final = 0;           // Noncompliant
	virtual void H() noexcept final {}             // Noncompliant
	virtual void J() noexcept {}                   // Compliant
	virtual void K() noexcept {}                   // Compliant
	virtual ~Base() {}                             // Compliant
	virtual void M() noexcept {}                   // Compliant
	virtual void Z() noexcept {}                   // Compliant
	virtual void X() throw() {}                    // Compliant
	virtual void Y() noexcept {}                   // Compliant
};                                                 

class Derived : public Base                        
{                                                  
public:                                          
	~Derived() {}                                  // Noncompliant
	virtual void F() noexcept override {}          // Noncompliant
	void K() noexcept override final {}            // Noncompliant
	virtual void M() noexcept {}                   // Compliant
	void Z() noexcept override {}                  // Compliant
	void J() noexcept {}                           // Noncompliant
	void J(int) noexcept {}                        // Compliant
	virtual void X() throw() final {}              // Noncompliant
	virtual void Y() noexcept override final {}    // Noncompliant
};
class DD: public Derived{
//	void J(int) noexcept override{}       //Compilation error
};
main(){
	//...
}

  • The destructor of the derived class ~Derived() is a virtual function. Its declaration violates this rule because the declaration contains none of the three specifiers for virtual functions.

  • The declaration of the pure virtual function Base::G() also violates this rule because the declaration contains both virtual and final as specifiers. A pure virtual function that is also specified as final is redundant.

  • The declaration of the virtual function Derived::J() violates this rule because Derived::J() implicitly overrides the virtual function Base::J() without using the specifier override.

  • The declarations of the virtual functions Derived::X() and Derived::Y() violate this rule because their declarations use more than one specifier.

The declaration of the function DD::J(int) produces a compilation error because DD::J(int) is trying to override Derived::J(int). Because Derived::J(int) has a different signature than Base::J(), perhaps by error, Derived::J(int) is no longer a virtual function. Attempting to override Derived::J(int) by DD::J(int) results in a compilation error. Using exactly one specifier in the declaration of virtual functions can help detect errors.

Check Information

Group: Derived classes
Category: Required, Automated

Version History

Introduced in R2020a