Start here

Home
About Klocwork
What's new
Fixed issues
Release notes
Installation

Reference

C/C++ checkers
Java checkers
C# checkers
MISRA C 2004 checkers
MISRA C++ 2008 checkers
MISRA C 2012 checkers
MISRA C 2012 checkers with Amendment 1
Commands
Metrics
Troubleshooting
Reference

Product components

C/C++ Integration build analysis
Java Integration build analysis
Desktop analysis
Refactoring
Klocwork Static Code Analysis
Klocwork Code Review
Structure101
Tuning
Custom checkers

Coding environments

Visual Studio
Eclipse for C/C++
Eclipse for Java
IntelliJ IDEA
Other

Administration

Project configuration
Build configuration
Administration
Analysis performance
Server performance
Security/permissions
Licensing
Klocwork Static Code Analysis Web API
Klocwork Code Review Web API

Community

View help online
Visit RogueWave.com
Klocwork Support
Rogue Wave Videos

Legal

Legal information

MISRA.BASE.MANYDEFS

Both overriding and overridden virtual functions have definitions.

MISRA-C++ Rule 10-3-1 (required): There shall be no more than one definition of each virtual function on each path through the inheritance hierarchy.

Rationale

The main aim of this rule is clarity for maintainers and reviewers, by ensuring that the version of a function that can be executed from any point in a class hierarchy is unambiguous. Additionally, where classes form a diamond hierarchy, call by dominance ([1] §10.3(11)) may occur resulting in a call to a function that is inconsistent with developer expectations. This rule also prevents call by dominance.

Exception

Destructors may be declared virtual in multiple members of a class hierarchy. If a function is declared pure and defined in the same class, then that definition is ignored for this rule.

Example

class A
{
public:
   virtual void f1 ( ) = 0;   // f1 is pure
   virtual void f2 ( ) = 0;   // f2 is pure
   virtual void f3 ( ) { }    // f3 is not pure
   virtual void f4 ( ) = 0;   // f4 is pure
   virtual ~A(); // destructor
};
// A::f1 is both pure and has a definition
void A::f1 ( )
{
}
// A::f4 is both pure and has a definition
void A::f4 ( )
{
}
class B : public A
{
public:
   virtual void f2 ( ) { }    // Compliant: f2 pure in A and
                              // defined in B
   virtual void f3 ( ) { }    // Non-compliant: f3 defined in A and B
   virtual void f4 ( ) = 0;   // Compliant: f4 is pure in A and in B
   virtual ~B();              // Compliant: destructor
};
// Compliant by Exception - f4 defined in A but also declared pure in A
void B::f4 ( )
{
}
class C : public B
{
public:
   virtual void f1 ( ) { }    // Compliant: f1 defined in A and C
                              // but was pure in A
   virtual void f2 ( ) { }    // Non-compliant f2: defined in B and C
                              // and not declared pure in B
   virtual void f4 ( ) { }    // Compliant by Exception: f4 defined in A
                              // and B but also declared pure in A and B
};
class D : public C
{
public:
   virtual void f1 ( ) { }    // Non-compliant f1: defined in C and D
                              // as well as A
   virtual ~D();              // Compliant: destructor
};
// Call by dominance example
class V
{
public:
   virtual void foo ( )
   {
   }
};
class B1 : public virtual V
{
public:
   virtual void foo ( )  // Non-compliant
   {
   }
};
class B2 : public virtual V
{
public:
   void f1 ( )
   {
      foo();  // V::foo would appear to be the only
              // candidate to be called here
}
};
class D : public B1, public B2
{
public:
   void f2 ( )
   {
      f1();
   }
};
B2 b2;
b2.f1();  // calls V::foo by normal inheritance rules
D d;
d.f2();   // calls B2::f1 which now calls B1::foo
          // "by dominance"
d.f1();   // also calls B1::foo "by dominance"