有効なC ++句37:継承とオブジェクト指向和(継承されたデフォルトのパラメータ値を再定義していません)

序文

  • 継承階層に導入点で36、派生クラスは、好ましくは、唯一の非仮想ベースクラスを非表示にすることなく、仮想関数をオーバーライドカバー
  • そのため、紹介するには、この句は「デフォルトのパラメータ値が継承再定義しないでください」という点で仮想関数のためであります
  • 重要な概念:仮想関数を動的にバインドされますが、デフォルトのパラメータ値の仮想関数は、スタティックにバインドされています

まず、静的な型と動的な型

  • 静的タイプ:タイプによって採用された宣言で
  • ダイナミックタイプ:現在の知識オブジェクトタイプ

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

  • ここでは、継承階層があります
class Shape {
public:
    enum ShapeColor { Red, Green, Blue };
    virtual void draw(ShapeColor color = Red)const = 0;
};

class Rectangle :public Shape {
public:
    virtual void draw(ShapeColor color = Green)const = 0;
};

class Circle :public Shape {
public:
    virtual void draw(ShapeColor color)const = 0;
};

  • 今、私たちは、次のコードを定義し、それらは彼らが何を指していない問題であるので、静的な型は形状である*、ピンターツーShpae型として宣言されます。
Shape* ps;                 //静态类型为Shape*
Shape* pc = new Circle;    //静态类型为Shape*
Shape* pr = new Rectangle; //静态类型为Shape*
  • どんな行動があるだろうオブジェクト手段のダイナミックなタイプ。例えば:
Shape* ps;
Shape* pc = new Circle;
Shape* pr = new Rectangle;

ps = pc; //ps的动态类型如今是Circle*
ps = pr; //ps的动态类型如今是Rectangle*
  • 私たちは、仮想関数を呼び出すための構文に従って、そのダイナミックなタイプに応じて決定されることを知っています。例えば:
Shape* ps;                 
Shape* pc = new Circle; 
Shape* pr = new Rectangle;

pc->draw(Shape::Red); //调用Circle::draw(Shape::Red)
pr->draw(Shape::Red); //调用Rectangle::draw(Shape::Red)

第二に、仮想関数を静的にバインドされているデフォルトのパラメータ値

  • 動的にバインドされた仮想関数を呼び出すための時間が、しかし、仮想関数のデフォルトのパラメータ値は静的にバインドされています
  • 次のコードを参照してください。
    • 私たちは、仮想関数を動的にバインドされていることを知っているコールが長方形であるので、PR Rectangleの動的な型を描く::()
    • しかし、仮想デフォルトのパラメータ値が静的にバインドされた関数であり、上記のクラス描画の定義における矩形()パラメータなしで機能するが、静的型PR形状ポインタに起因するので、ドロー()関数のデフォルトのパラメータ値これは、形状のパラメータ値の形状::ドロー()関数です::レッド
Shape* pr = new Rectangle;
pr->draw(); //调用的是Rectangle::draw(Shape::Red)


//Circle也是相同的道理
Shape* pc = new Circle;
pc->draw(); //调用的是Circle::draw(Shape::Red),而不是Circle::draw(Shape::Green)
  • なぜ、この動作を設計:作業効率という。デフォルトのパラメータ値が動的結合されている場合、コンパイラは、現在の場所で「コンパイル時の決定で」より遅く、より複雑なメカニズムよりもある、実行時に仮想関数のための適切なパラメータのデフォルト値を決定するために、いくつかの方法でなければなりません

第三に、継承されたデフォルトのパラメータ値を再定義していません

  • 第二にすることで、我々はことを知っているデフォルトのパラメータ値仮想関数が静的にバインドされています。あなたは仮想関数を呼び出すとき、それは予期しない結果を生成するため、したがって、我々は、継承されたデフォルトのパラメータ値を再定義していない()(PCで引き分けを呼び出すコード上記の例です)

第四に、デフォルトのパラメータ値仮想関数の勧告に対する応答は、与えられました

非効率的なプログラムの外観

  • 基底クラスと派生クラスの一貫性のため、および非効率的な方法であるデフォルトパラメータ値ベースを設定し、派生クラスの仮想関数が一致しています
  • 例えば:
class Shape {
public:
    enum ShapeColor { Red, Green, Blue };
    virtual void draw(ShapeColor color = Red)const = 0;
};

class Rectangle :public Shape {
public:
    virtual void draw(ShapeColor color = Red)const;
};

class Circle :public Shape {
public:
    virtual void draw(ShapeColor color = Red)const;
};
  • 非効率的な理由から:
    • ①コードの重複
    • ②依存性は、基本クラスでのデフォルトのパラメータ値が変更された場合は、再度変更されたデフォルトのパラメータ値派生クラスを必要とし、高すぎます

クラスを定義するNVIの方法

  • デフォルトのパラメータ値のための仮想関数でNVI技術は、デフォルトパラメータの基底クラスを避けるために、派生クラスの値が一致しないために、我々はこのアプローチを取ることができ、項目36を発表
  • 次のようにコードが定義されています。
class Shape {
public:
    enum ShapeColor { Red, Green, Blue };
    void draw(ShapeColor color = Red)const { //因为是non-virtual函数,因此不建议派生类隐藏
        doDraw(Red);
    }
private:
    //真正的工作在此处完成,派生类可以重写
    virtual void doDraw(ShapeColor color)const = 0;
};


class Rectangle :public Shape {
private:
    virtual void doDraw(ShapeColor color)const = 0;
};
  • 実際の機能を完了するdoDraw()関数上、及びタイプShapeColorを受け付け
  • 私たちは、そのパラメータレッドデフォルト、および非仮想関数はそう、非表示に派生クラスをお勧めしません、非仮想関数drawを定義したドロー()のデフォルトの関数を呼び出し、パラメータは常に赤になり、それが基底クラスや派生クラスであるかどうか私たちの究極の目標に到達します

V.の概要

  • あなたがカバーされるべき唯一のもの - - それは動的バインディングは決してデフォルトのパラメータ値は、静的結合、および仮想関数であるため、継承されたデフォルトのパラメータ値を再定義していません
发布了1525 篇原创文章 · 获赞 1085 · 访问量 45万+

おすすめ

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