検索

ホームページ  >  に質問  >  本文

复合模型 - 关于《effective C++》条款39:明智而审慎地使用private继承 中的的一个问题

我们有这样一个定时器

class Timer{
public:
    explict Timer(int tickFrequency);
    virtual void onTick() const;
    ...
};

  然后比较了继承和复合。
  继承的代码:

class Widget:private Timer{
private:
    virtual void onTick() const;
    ...
};

  然后书上说:

首先,你或许会想设计Widget使它得以拥有derived classes,但同时你可能会想阻止derived classes重新定义onTick。如果Widget继承自Timer,上面的想法就不可能实现,即使是private继承也不可能。

  首先,这里说的是重新定义。重定义函数要求基类中的对应函数是非虚的,而给出的代码是虚的。如果说的是重写,我们不想基类中的对应函数被重写就不要讲它声明为virtual不就可以了吗,书上到底想要说的是一个什么问题???

PHP中文网PHP中文网2803日前551

全員に返信(1)返信します

  • 阿神

    阿神2017-04-17 15:34:45

    これはまさに私たちが探しているものです。Timer オブジェクトは必要な頻度でティックするように構成でき、ティックごとに仮想関数を再定義できます。その仮想関数を使用して、ウィジェット ワールドの現在の状態を調べます。

    Timer の前述の説明によれば、onTick は仮想関数でなければならないことがわかります。これは、Timer の派生クラスが、この関数の動作を変更するために onTick をオーバーライドする必要があるためです (たとえば、新しい Timer を定義する場合)。 redefineは書き直すという意味です。

    ウィジェットにタイマーが必要になったので、独自のニーズに合わせてタイマーの onTick 関数を書き直す必要がある場合があります。同時に、ウィジェットから派生したクラスが onTick の動作を変更できないようにする必要があります。

    ウィジェットに onTick を「所有」させるには、継承または集約という 2 つのオプションがあります。

    Widget が Timer を継承する場合、onTick はオーバーライドできます。ただし、この場合、Widget は Timer を継承し、onTick は Timer で仮想関数として宣言されるため、Widget の派生クラスも onTick をオーバーライドできます。 (間接基本クラスで宣言された仮想関数もオーバーライドできます。派生クラスは、基本クラスで宣言された仮想関数をキャンセルできません。仮想関数のセットは、基本クラスで仮想として宣言する必要があるだけです。)

    集約により、継承によって引き起こされるこの問題を回避できます。ウィジェットは Timer の派生クラスを集約し、必要に応じて派生クラスの onTick をオーバーライドします。本に記載されている例のように (WidgetTimer で onTick を宣言する場合の仮想は冗長です):

    リーリー

    関係ありません:

    仮想関数はキャンセルできませんが、フィールドのネストされた関係を使用して、基本クラスの仮想関数を非表示にすることができます。たとえば、同じ名前の呼び出し可能オブジェクトを定義します。このようにして、一部の特定の呼び出しでは、仮想メンバー関数ではなくオブジェクトが直接検索されます。しかし、それでも書き換えを防ぐことはできません

    リーリー

    返事
    0
  • キャンセル返事