効果的なC ++項目32:オブジェクト指向の継承(必ずお使いのパブリック継承型である-関係します)

Aは、 "ある-" コンセプト

  • Cと行動++オブジェクト指向プログラミングは、:最も重要なルールは、ということである公共の継承(パブリック継承)手段との間の関係が「1」()の
  • あなたが公共のフォームを持つクラスD継承クラスBを加えた場合は、コンパイラに指示です。
    • オブジェクトDの各タイプは、それぞれ、また、タイプBのオブジェクトです。一方ではありません
    • B、Dは、オブジェクトとして使用することができる場合のオブジェクトを使用することができます。一方ではありません

ケース・プレゼンテーション

  • 次のパブリック人からStudentクラスの継承
class Person {};
class Student :public Person {};
  • 引数の任意のタイプは、人(対個人ポインタ、または参照・ツー・パーソン)を得、そして生徒(対スチューデントポインタまたは参照対スチューデント)オブジェクトを受け入れることができます
  • 例えば:
void eat(const Person& p);
void study(const Student& s);

int main()
{
    Person p;
    Student s;

    eat(p);    //正确
    eat(s);    //正确
    study(s);  //正确
    study(p);  //错误
 
    return 0;
}
  • 唯一の公共の継承の確立の前に上記のルール。保護された、プライベート保持していません

第二に、意匠権継承モデル

  • 鳥はペンギンは鳥で、飛ぶことができます。下のエラーの継承モデルを設計するかもしれない、私たちはそう:
    • 彼らは鳥、ペンギンですが、ペンギンが飛ぶことはできませんが、
    • デザイン、我々は鳥の間違っているだろう()仮想関数はペンギンにクラスを派生飛びます
//鸟类
class Bird {
public:
    virtual void fly();
};

//企鹅,也继承了fly()虚函数
class Penguin :public Bird {};
  • 私たちは、上記のコードを変更する必要があり、次のように適切なモデルは次のようになります。
//鸟类
class Bird {
    //无fly()函数
};

//会飞的鸟类
class FlyingBird :public Bird {
public:
    virtual void fly();
};

//企鹅不会飞
class Penguin :public Bird {

};

第三には、するために、確認の関係に代わりに「実行」の関係を確認するために、「コンパイル」

  • そして、上記の鳥やペンギンを発行
  • ペンギンは飛ぶことはできませんが、我々はまだバード()関数を飛ぶ定義された作り、その後、ペンギンは鳥、上記の違いは、我々はペンギンがフライ()関数の実装でエラーを報告しましょうということで継承されてみましょう(ランタイム実行)コードは以下の通りであります:
class Bird {
public:
    virtual void fly();
};

void error(const std::string& msg);
class Penguin :public Bird {
public:
    virtual void fly() {
        error("Attempt to make a penguin fly!");
    }
};
  • 上記のコードは実行時にこのようなエラーをチェックすることです
  • レッツ・デザインは、コンパイラができ、コンパイル時にこのエラーを飛べないペンギンをチェックアウトします。コードは以下の通りであります:
class Bird {
    //无fly()函数
};


class Penguin :public Bird {
    //...
};

Penguin p;
p.fly();
  • 要約:
    • 私たちの上に2つの方法の検出は、そのようなエラーを「ペンギンは、飛ぶことができません」。実行中のテストのために一つ、コンパイル時に検出するための1
    • もちろん、私たちはその代わりに、デザインの継承への最初のアプローチ(ランタイム)の第二の方法(コンパイル時に)願って、コンパイル時にペンギンが飛ぶことができない関係を決定することを願っています

フォー、ある-いくつかの例外のモデル

ケースプレゼンテーションを考えてみましょう

  • 私たちは、(長方形の)長方形から継承された正方形のクラス(スクエア)publicクラスをしましょう次のとおりです。

  • 次のように長方形クラスコードを定義します。
class Rectangle {
public:
    virtual void setHeight(int newHeight); //设置高
    virtual void setWidth(int newWidth);   //设置宽

    virtual void height()const; //返回高
    virtual void width()const;  //返回宽
};
  • 以下の機能がありますが、以下の機能は常にアサートされている機能のみ幅、高さを変更し、変更されていないため、真であります:
//这个函数用来增加r的面积
void makeBigger(Rectangle& r)
{
    int oldHeight = r.height(); //取得旧高度
    
    r.setWidth(r.width() + 10); //设置新宽度
    
    assert(r.height() == oldHeight); //判断高度是否改变
}
  • スクエアクラスコードは、次のことを定義します。
class Square :public Rectangle {
    //...
};
  • 今、私たちは、次のコードを持っています:
Square s; //正方形类

//...

assert(s.width() == s.height()); //永远为真,因为正方形的宽和高相同
makeBigger(s); //由于继承,我们可以增加正方形的面积

//...
assert(s.width() == s.height()); //对所有正方形来说,应该还是为真
  • 今すぐ上記のコードを考えてみます。
    • 最初のステップは、我々は、正方形の幅と高さを決定し、原則によると、アサートがtrueを返す必要があります
    • 第二工程は、高さを変えずに幅を変更makeBigger()関数と呼ばれています
    • 第3のステップは、まだ真を返す必要があり、再びアサートを呼び出すことで、ここでの正方形の理由
  • 今、私たちは見ることができます:
    • 我々が言及前述しながら、クラスの基本コードに作用し、派生クラスも使用して実行することができます
    • しかし、ここでは(例えば、高さのみを変更することなく、幅を変更する)クラス長方形のコードの目的の一部を見ることができるが、(長方形の幅と高さが一致する必要があるため)、矩形形状で実現することができます
    • -さの関係は、クラス間に存在するだけではなく。他の2人の一般的な関係は、()-あり、かつある-の実装-項(何かを実現するために応じて)。これらの関係は、節38と39で説明されています。これらの関係を形作るである-されている原因の設計ミス

V.の概要

  • 「公共の継承」平均であります - 。すべてのものの際に基底クラスに適しても、各派生クラスのオブジェクトは、ベースクラスのオブジェクトであるため、派生クラスに適用する必要があります

发布了1504 篇原创文章 · 获赞 1063 · 访问量 43万+

おすすめ

転載: blog.csdn.net/qq_41453285/article/details/104757241