AUTOSAR C++14 Rule A10-1-1
Class shall not be derived from more than one base class which is not an interface class
説明
ルール定義
Class shall not be derived from more than one base class which is not an interface class.
根拠
複数の非インターフェイス クラスを継承するクラスは、基本的に、複数の実装にアクセスできます。そのため、コードの保守が困難になる可能性があります。
クラスが複数の非インターフェイス クラスを継承する場合は、同じメンバー関数がそれらの基底クラス内に存在する可能性があるため、派生クラス内でオーバーライドする必要があります。これらの基底クラス自体が共通の基底クラスを継承する (ダイヤモンド構造) 場合は、この可能性が高まります。
インターフェイス クラス Interface に 2 つの具象的な実装 (Impl1 と Impl2) が含まれており、クラス Final は両方の実装から派生しているとします。クラス階層は次のダイヤモンド構造をしています。

以下の問題が発生する可能性があります。
あいまいさを排除するために最終派生クラスでオーバーライドが必要となる。
Impl1とImpl2の両方の実装にクラスInterfaceのすべてのメソッドのコピーが含まれています。どのコピーがFinalオブジェクトを通して呼び出される可能性があるかを明確にするために、通常は、スコープ解決演算子::を使用して両方のコピー (または、選択した 1 つのコピー) を明示的に呼び出すFinalクラスで、すべてのメソッドのオーバーライドをもう一つ作成します。下の例を参照してください。クラス
Interfaceに新しい純粋なバーチャル関数を追加するたびに、直接派生クラスで実装を作成する必要があるだけでなく、クラス階層全体を追跡して、クラスFinalでそれらの実装のオーバーライドを作成する必要があります。オリジナル クラス
Interfaceがインターフェイス クラスでない場合は、問題がより深刻です。継承がバーチャルでない場合は、Impl1とImpl2でInterfaceのメソッドの 2 つのコピーが "暗黙的に" 作成されます (ダイヤモンド問題)。階層内のすべてのクラスを初期化する責任がある最終派生クラス:
多重継承における二重初期化を避けるために、C++ 標準では、最上位の派生クラスでそれより前のすべてのクラスのコンストラクターを呼び出す必要があります。
前述の例で、
Finalクラスのコンストラクターは、Impl1とImpl2のコンストラクターを呼び出す必要があるだけでなく、それらの親クラスであるInterfaceのコンストラクターも呼び出す必要があります。直接の親を越えてトレースし、最終派生クラスで呼び出すコンストラクターを判別する必要があります。
複数のクラスから 1 つのクラスを派生できるものの、複数のクラスのうち 1 つしか非インターフェイス クラスにできないという制限が多重継承に適用される場合は、このような問題は発生しません。インターフェイス クラスは、純粋なバーチャル関数と、コンパイル時の定数 (静的、contexpr) であるデータ メンバーのみを含むクラスです。このクラスは状態を持ちません。このクラスの唯一の用途は派生クラスによって実装されることです。
多重継承は、1 つのクラスが 1 つの具象実装を拡張するだけでなく、インターフェイス クラスで表される他のアイデアも実装する、という状況に合わせて設計されています。それ以外の用途に多重継承を使用した場合は、保守に危険をもたらす可能性があります。
Polyspace 実装
チェッカーは、複数の基底クラスが非インターフェイス クラスである多重継承にフラグを設定します。
インターフェイス クラスは、純粋なバーチャル関数と、コンパイル時の定数 (静的、contexpr) であるデータ メンバーのみを含むクラスです。コンストラクターまたはデストラクターが =default または =delete に設定されます。
トラブルシューティング
ルール違反が想定されるものの、Polyspace® から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。
例
チェック情報
| グループ: 派生クラス |
| カテゴリ: Required、Automated |
バージョン履歴
R2020a で導入