This rule is part of MISRA C++:2023.
Usage of this content is governed by Sonar’s terms and conditions. Redistribution is
prohibited.
Rule 15.1.2 - All constructors of a class should explicitly initialize all of its virtual base classes and immediate base classes
Category: Advisory
Analysis: Decidable,Single Translation Unit
Amplification
This rule applies to all user-provided constructors that are not defaulted.
A base class is considered as explicitly initialized by a constructor when:
- The base class is initialized in the member initializer list of the constructor; or
- The constructor is a delegating constructor, assuming that the delegated-to constructor conforms to this rule.
Rationale
This rule reduces the chance of confusion over which constructor will be used, and with what parameters.
Exception
A class is empty when it has no non-static data members, no virtual member functions, no virtual base classes, and only empty
base classes. A base class that is empty need not be initialized, as there is nothing to initialize.
Example
class A
{
public:
A() {} // Rule does not apply - no base classes
};
class B : public A
{
public:
B() {} // Compliant by exception
};
class V
{
public:
V() {} // Rule does not apply - no base classes
V( int32_t i ): i ( i ) {} // Rule does not apply - no base classes
private:
int32_t i = 0;
};
class C1 : public virtual V
{
public:
C1() : V { 21 } {} // Compliant
};
class C2 : public virtual V
{
public:
C2() : V { 42 } {} // Compliant
};
In the following, there would appear to be an ambiguity as D only includes one copy of V. Which version of
V's constructor is executed and with what parameter? In fact, V's default constructor is always executed. This would be the
case even if C1 and C2 constructed their bases with the same integer parameter.
class D: public C1, public C2
{
public:
D() {} // Non-compliant
};
This is clarified by making the initialization explicit:
D() : V {}, C1 {}, C2 {} {} // Compliant - V::i == 0
struct E
{
int32_t i;
int32_t j;
};
class F : public E
{
public:
F( int32_t val ) : E { val } // Compliant - E is initialized by aggregate
{} // initialization, with E::j initialized to 0
F() : F ( 0 ) {} // Compliant - delegates to the other constructor
};
class G : public A // Rule does not apply - no user-provided
{ // constructor
};
class H : public A, public V // Rule does not apply - no user-provided
{ // constructor
public:
using V::V; // Subobject 'A' implicitly initialized
};
Copyright The MISRA Consortium Limited © 2023