3

抽象ファクトリパターンを念頭に置いて、具体的なファクトリがcreateButton * s *仮想メソッドをオーバーライドし、より幅広いボタンの配列を返す必要があるクラス階層があると想像してください。C ++は共変の戻り型のみをサポートするため、これを解決するための洗練された回避策は何でしょうか。dynamic_cast?

私の要件に合うようにGoFの例を修正したもの:

class Button {
public:
        virtual void paint() = 0;
        virtual ~Button(){
        }
};

class WinButton: public Button {
public:
        void paint() {
                cout << "I'm a WinButton";
        }
};

class OSXButton: public Button {
public:
        void paint() {
                cout << "I'm an OSXButton";
        }
};

class GUIFactory {
public:
        virtual Button * createButtons() = 0;
        virtual ~GUIFactory(){
        }
};

class WinFactory: public GUIFactory {
public:
        WinButton* createButtons() {
                return new WinButton[2];
        }

        ~WinFactory(){
        }
};

class OSXFactory: public GUIFactory {
public:
        OSXButton* createButtons() {
                return new OSXButton[2];
        }

        ~OSXFactory(){
        }
};

そして、アプリケーションのスケルトン:

Application(GUIFactory * factory) {
                Button* buttons = factory->createButtons();
                for(...) {...}
        }
4

3 に答える 3

2

できません。自問してみてください、発信者ですか、deleteそれともdelete[]それですか?配列に含まれる要素の数をどのようにして知ることができますか?生のポインタリターンでこれらの問題のいずれかを解決する方法はありません。ですから、あなたの質問に対する簡単な答えは、これはできないということです。呼び出し先は、リターンタイプ(ボタンが1つなのか多数なのか)と、完了時にそれらをクリーンアップする方法を知っている必要があります。

Undefined Behaviourを呼び出さずに、最初以外の要素にアクセスすることもできません。

ファクトリは、個々のオブジェクトを構築することになっています。複数必要な場合は、ファクトリ関数を複数回呼び出します。

1つ(wtf?)しか期待していなかったときに、一度に複数のボタンを処理できるコードが魔法のようにあったとしても、複数のボタンを安全に返す必要があります。つまりstd::vector<smart_pointer<Button>>

于 2011-12-23T14:32:40.620 に答える
1

ファクトリメソッドで配列を作成し、クライアントへのポインタを返す必要はありません。そうすれば、ボタンがいくつあるかわからないので、得られたもので実際には何もできません。

std::vector<shared_ptr<Button>>C ++ 11では、またはを返すことができますstd::vector<unique_ptr<Button>>

Buttonただし、おそらくこのソリューションを選択します。カウントとインデクサーのみを公開する、ある種のカスタム「読み取り専用」コレクションを返します。シナリオに適している場合は、イテレータを追加することもできます。

class ButtonCollection
{
public:
    size_t getCount() const {}
    Button& getAt(size_t index) {}
    const Button& getAt(size_t index) const {}

private:
    friend class GUIFactory;

    ButtonCollection() {}
    add(Button* button) {}
    // Or in C++11:
    // add(std::unique_ptr<Button> button) {}
};

アプリケーションスケルトンの場合:

Application(GUIFactory& factory)
{
   std::auto_ptr<ButtonCollection> buttons = factory.createButtons();
   // Or in C++11:
   //std::unique_ptr<ButtonCollection> buttons = factory.createButtons();
   for(...) {...}
}
于 2011-12-23T11:15:32.050 に答える
0

boost::ptr_vectorまたはhttp://www.boost.org/doc/libs/1_48_0/libs/ptr_container/doc/ptr_vector.htmlの使用を検討してくださいboost::ptr_array

于 2011-12-23T14:38:03.613 に答える