0

親の同じ関数を呼び出しながら、派生関数の動作を上書きします。たとえば、C :: foo()を参照してください。A:: fooの動作はありますが、拡張されています。パターンになるのは簡単すぎますか?

class A
{
public:
    virtual ~A() {}
    virtual void foo(){ MSG("A::foo");}
};

class B : public A
{
public:
    virtual void foo(){ MSG("B::foo");}
};

class C : public B
{
public:
    virtual void foo(){ 
        A::foo(); //here still have the behaviour of A::foo but extended it
        MSG("C::foo");
    }
};

void callFoo(A* p)
{
    p->foo();
}

int main()
{
    boost::scoped_ptr<A> myPtr(new A());
    callFoo(myPtr.get());

    myPtr.reset(new B());
    callFoo(myPtr.get());

    myPtr.reset(new C());
    callFoo(myPtr.get());

    return 0;
}
4

2 に答える 2

3

「シンプルだが便利なパターン」とは、「言語機能」を意味します。言語機能を一度だけ使用して、それをパターンと呼ぶことはできません。それはパターンではありません。言語機能を使用しているのはあなただけです。つまり、おめでとうございます。言語機能を使用することは、言語でプログラムを構築するための重要な方法だと思いますが、どのパターンからも遠い道のりです。

于 2012-09-14T11:32:59.620 に答える
2

「パターン」と呼ばれるように複雑なデザイン要素である必要はありません。

ただし、それが有用であるという要件があります。正確で、一貫性があり、効率的で柔軟な設計を簡単に作成できるようになります。基本クラスに便利な機能を実装し、それを手動で呼び出すことを忘れないように派生クラスに負担をかけることは、実際にはその要件を満たしていないため、「アンチパターン」とラベル付けしたくなるでしょう。中間の基本クラスを追加し、派生クラスの実装者が実際に必要なオーバーライドを把握することを期待することは、「混乱を招く混乱」に沿ったものです。

この状況で善意のパターン(有名な本で大文字を使用して説明されている)が必要な場合は、テンプレートメソッドが適切かもしれません-基本クラスには、いくつかの一般的な機能を実行する非仮想関数が含まれており、作業の一部をに委任しますオーバーライドできるプライベートで純粋な仮想関数。個人的には、さらに一歩進んで別のクラスに委任します。これは、各クラスに単一の責任を与え、抽象インターフェイス以外から継承することを避け、次のようなものを与えるためです。

class FooInterface {
public:
    virtual ~FooInterface() {}
    virtual void foo() = 0;
};

class A {
public:
    void foo(FooInterface & impl) {
        MSG("A::foo"); // Happens whatever the implementation does
        impl.foo();
    }
};

class C : public FooInterface {
    virtual void foo() {
        // We don't have to worry about A at all
        MSG("C::foo");
    }
};
于 2012-09-14T12:09:33.323 に答える