メインコンテンツ

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.

説明

ルール定義

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

根拠

基底クラスのコンストラクターのすべてを明示的に呼び出すわけではない派生クラスでは、オブジェクト構築の際にどの基底クラスのコンストラクターが使用されるかに関してあいまいさが生じます。

次のダイヤモンド クラス階層を考えてください。

           SuperClass 
             /    \ 
       ClassA      ClassB 
             \    / 
             ClassC 

ClassC オブジェクトを構築するときに、ClassA または ClassB のどちらが SuperClass を初期化するのかが明白ではありません。意図していない初期値で SuperClass が構築されると、予期しないコードの動作になるリスクが高くなります。ClassC を使用して SuperClass の初期化に使用するコンストラクターを明示的に指定すると、このダイヤモンド階層のあいまいさが解決されます。

無効な状態または意図しない初期値を回避するには、派生クラス コンストラクターの初期化リスト内で必要な基底クラス コンストラクターを直接呼び出します。

Polyspace 実装

Polyspace® は、派生クラス コンストラクターの初期化リストが次のようになっている場合、コンストラクターにフラグを設定します。

  • バーチャル基底クラスのコンストラクターを明示的に呼び出していない。

  • 直接非バーチャル基底クラスのコンストラクターを明示的に呼び出していない。

トラブルシューティング

ルール違反が想定されるものの、Polyspace から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

#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;   
}  

この例では、基底クラスと非静的データ メンバーがクラス コンストラクターによって明示的に初期化されていないため、Polyspace はこのコンストラクターにフラグを設定します。次に例を示します。

  • B クラスのコンストラクターは基底クラス A を明示的に初期化していないため、このルールに準拠していません。この問題を解決するには、B コンストラクターの初期化リスト内で A クラスのコンストラクターを呼び出します。

  • D クラスのコンストラクターは、初期化リスト コンストラクターの呼び出しによって、直接非バーチャル基底クラスの両方を明示的に初期化しているため、ルールに準拠しています。

#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;  
} 

この例では、基底クラスと非静的データ メンバーがクラス コンストラクターによって明示的に初期化されていないため、Polyspace はこのコンストラクターにフラグを設定します。次に例を示します。

  • B クラスのコンストラクターはその直接基底クラスを初期化リスト内で明示的に初期化しているため、ルールに準拠しています。

  • C クラスのコンストラクターはその直接基底クラス A を明示的に呼び出していないため、ルールに準拠していません。この問題を解決するには、C コンストラクターの初期化リスト内で A クラスのコンストラクターを呼び出します。

  • D クラスのコンストラクターはそのバーチャル基底クラス A を明示的に呼び出していないため、ルールに準拠していません。複数のバーチャル継承であることから、最上位の派生クラスがバーチャル基底クラスを初期化する必要があります。この問題を解決するには、D コンストラクターの初期化リスト内で A クラスのコンストラクターを呼び出します。

チェック情報

グループ: Special Member Functions
カテゴリ: 推奨

バージョン履歴

R2013b で導入


1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.

The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:

  • MISRA C:2004

  • MISRA C:2012

  • MISRA C:2023

  • MISRA C++:2008

  • MISRA C++:2023

MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.