Main Content

MISRA C++:2008 Rule 12-1-2

All constructors of a class should explicitly call a constructor for all of its immediate base classes and all virtual base classes

Description

Rule Definition

All constructors of a class should explicitly call a constructor for all of its immediate base classes and all virtual base classes.

Rationale

Derived classes that do not explicitly call all base class constructors create ambiguity over which base constructor is used during object construction.

Consider this diamond class hierarchy.

           SuperClass 
             /    \ 
       ClassA      ClassB 
             \    / 
             ClassC 

When constructing a ClassC object, it is unclear whether ClassA or ClassB is responsible for initializing the SuperClass. If the SuperClass is constructed with unintended initial values, then the risk of unexpected code behavior increases. Having ClassC explicitly specify the constructor used to initialize the SuperClass resolves the diamond ambiguity.

To avoid invalid state and unintended initial values, directly call the necessary base class constructors in the derived class constructor initialization list.

Polyspace Implementation

Polyspace® flags the constructor of a derived class if its initialization list:

  • Does not explicitly call the constructors of the virtual base classes.

  • Does not explicitly call the constructors of the direct nonvirtual base classes.

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 A {  
public:  
	A() : a{1} {}  
	virtual void abstractA() const = 0;  
private:  
	int a;  
};  

class B : public  A {  
public:  
	B() : b{1} {} //Noncompliant 
	void abstractA() const override {}  
private:  
	int b;  
};  

class C {  
public:  
	C() : c{3} {}  
private:  
	int c;  
};  

class D : public B, public C {  
public:  
	D() : B(), C(), e{5} {} //Compliant 
private:  
	int e;  
};  

int main() {   
	D dName;  
	return 0;   
}  

In this example, Polyspace flags the class constructors that do not explicitly initialize the base classes and nonstatic data members. For instance:

  • The B class constructor is noncompliant because it is missing an explicit initialization of its base class A. To resolve this issue, call the A class constructor in the B constructor initialization list.

  • The D class constructor is compliant because it explicitly initializes both of its direct nonvirtual base classes through initialization list constructor calls.

#include <cstdint>   

class A { 
public: 
	A() : a{1} {} 
	virtual void abstractA() const = 0; 
private: 
	int a; 
}; 

class B : public virtual A { 
public: 
	B() : A(), b{1} {} //Compliant 
	void abstractA() const override {} 
private: 
	int b; 
}; 

class C : public virtual A { 
public: 
	C() : c{3} {} //Noncompliant 
	void abstractA() const override {} 
private: 
	int c; 
}; 

class D : public B, public C { 
public: 
	D() : B(), C(), e{5} {} //Noncompliant 
private: 
	int e; 
}; 

int main() {  
	D dName; 
	return 0;  
} 

In this example, Polyspace flags the class constructors that do not explicitly initialize the base classes and nonstatic data members. For instance:

  • The B class constructor is compliant because it explicitly initializes its direct base class within its initialization list.

  • The C class constructor is noncompliant because it does not explicitly call its direct base class A. To resolve this issue, call the A class constructor in the C constructor initialization list.

  • The D class constructor is noncompliant because it does not explicitly call its virtual base class A. As a result of multiple and virtual inheritance, the most derived class must initialize the virtual base class. To resolve this issue, call the A class constructor in the D constructor initialization list.

Check Information

Group: Special Member Functions
Category: Advisory

Version History

Introduced in R2013b