【Effection C++】読書ノート条項40:賢明かつ慎重な使用多重継承
3628 ワード
【Effection C++】継承とオブジェクト向け設計
条項40:賢明かつ慎重な多重継承の使用
まず小さな知識を紹介し、C++で名前を解析するときは、まず名前検索(役割ドメインに関連)、次にタイプマッチング、そこから最適なマッチングを見つけ、最後に可用性(private、protected、publicなど)をチェックします.
1.多重継承は単一継承よりも複雑であり、曖昧になる可能性が高い.
例は次のとおりです.
この例では、2つの知識点を示します.多重継承の場合,名前の曖昧さを生じやすく,クラスの維持が困難になる. 解析関数呼び出しの場合、名前を検索してから最適なタイプマッチングを探し、最後に可用性を判断します.Base 1はBase 2のfunのfunと同じように整合性が良いため、次のステップを待つのではなく、エラーを直接投げ出すことになります.
Derivedに呼び出す必要があると宣言した関数を表示する方法を改善します.
2.virtual継承とその複雑さ
多重継承は、より多くの曖昧さをもたらす可能性があるほか、虚継承が必要かどうかにも注意しなければならない.
このような状況を考えると、ベースクラスAに対してクラスBとクラスCがAに継承され、クラスDがBとC(多重継承)を同時に継承するので、クラスDにはAと2部Aのどちらを持つべきか.
C++にとって、デフォルトの状況はDにこの2つのAが存在することであるが、実際の生活の中で、経験は往々にして私たちに1つのDの中で1つのAしかないことを教えてくれた.
ただし、継承時に虚継承を追加した場合は、次のようになります.
ではDにはAが1部しかありません.
虚継承の要件は,ベースクラスから直接継承されたclassesがすべて「virtual継承」方式を採用し,これらのクラスを多重継承すると,最下層の派生クラスにベースクラスが1つしかないことである.
C++標準ライブラリ内のストリームはこのような形式を採用しており、親ストリームbasic_があります.ios,basic_istreamとbasic_ostreamはbasic_にそれぞれダミー継承されますios、basic_iostreamはbasic_に多重継承されていますistreamとbasic_ostream.
正しい行為の観点から,public継承はほとんどvirtualであるべきである.しかしvirtualをサポートするために、コンパイラはより多くの裏作業をしなければなりません.これにより、次の結果が得られます.
virtualで継承されたclassesを使用して生成されるオブジェクトは、non-virtualで継承された兄弟よりも体積が大きく、virtual base classesのメンバー変数にアクセスする場合、non-virtual base classesにアクセスするメンバー変数よりも速度が遅いことが多い.それ以外にvirtual baseの初期化の職責は継承システムの最下層classが担当する.
だから著者のvirtual base classesに対する忠告は: virtual classes継承を使用しない必要はありません.通常はnon-virtual classes継承 を使用してください. virtual base classesを使用する必要がある場合は、データの配置をできるだけ避けます.これにより、初期化および付与操作の心配がなくなります.
3.多重継承は確かに正当な用途がある
多重継承には複雑さがあるが,場合によってはその用途もある.Effective C++では、主に「publicがInterface classを継承する」と「privateが実現に協力するclassを継承する」の2つの組み合わせの例が提案されています.
条項40:賢明かつ慎重な多重継承の使用
まず小さな知識を紹介し、C++で名前を解析するときは、まず名前検索(役割ドメインに関連)、次にタイプマッチング、そこから最適なマッチングを見つけ、最後に可用性(private、protected、publicなど)をチェックします.
1.多重継承は単一継承よりも複雑であり、曖昧になる可能性が高い.
例は次のとおりです.
class Base1
{
public:
void fun(){}
};
class Base2
{
private:
void fun(){}
};
class Derived : public Base1, public Base2
{};
int main()
{
Derived d;
d.fun(); // : fun
return 0;
}
この例では、2つの知識点を示します.
Derivedに呼び出す必要があると宣言した関数を表示する方法を改善します.
class Derived : public Base1, public Base2
{
public:
void fun()
{
Base1::fun(); //
}
};
int main()
{
Derived d;
d.fun(); //OK
return 0;
}
2.virtual継承とその複雑さ
多重継承は、より多くの曖昧さをもたらす可能性があるほか、虚継承が必要かどうかにも注意しなければならない.
このような状況を考えると、ベースクラスAに対してクラスBとクラスCがAに継承され、クラスDがBとC(多重継承)を同時に継承するので、クラスDにはAと2部Aのどちらを持つべきか.
class A
{};
classs B:public A //B A
{};
classs C:public A //C A
{};
classs D:public B,public C //D A
{};
C++にとって、デフォルトの状況はDにこの2つのAが存在することであるが、実際の生活の中で、経験は往々にして私たちに1つのDの中で1つのAしかないことを教えてくれた.
ただし、継承時に虚継承を追加した場合は、次のようになります.
class B: virtual public A{…}
class C: virtual pulibc A{…}
ではDにはAが1部しかありません.
虚継承の要件は,ベースクラスから直接継承されたclassesがすべて「virtual継承」方式を採用し,これらのクラスを多重継承すると,最下層の派生クラスにベースクラスが1つしかないことである.
C++標準ライブラリ内のストリームはこのような形式を採用しており、親ストリームbasic_があります.ios,basic_istreamとbasic_ostreamはbasic_にそれぞれダミー継承されますios、basic_iostreamはbasic_に多重継承されていますistreamとbasic_ostream.
正しい行為の観点から,public継承はほとんどvirtualであるべきである.しかしvirtualをサポートするために、コンパイラはより多くの裏作業をしなければなりません.これにより、次の結果が得られます.
virtualで継承されたclassesを使用して生成されるオブジェクトは、non-virtualで継承された兄弟よりも体積が大きく、virtual base classesのメンバー変数にアクセスする場合、non-virtual base classesにアクセスするメンバー変数よりも速度が遅いことが多い.それ以外にvirtual baseの初期化の職責は継承システムの最下層classが担当する.
だから著者のvirtual base classesに対する忠告は:
3.多重継承は確かに正当な用途がある
多重継承には複雑さがあるが,場合によってはその用途もある.Effective C++では、主に「publicがInterface classを継承する」と「privateが実現に協力するclassを継承する」の2つの組み合わせの例が提案されています.