2017-04-09 14 views
2

これはよくあることかもしれませんが、私はこのようなものを実装するエレガントな方法を見つけることができないようです。私は、共通の属性ともう少し特化されている多くのサブクラスを組み合わせた基本クラスを持っている私の例ではメンテナンスにやさしい方法で多くの類似した(サブ)クラスを実装してください

class Fruit { 
    int m_weight; 
    int m_color; 
    int m_price; 
    public: 
    Fruit(int weight, int color, int price) 
     : m_weight(weight) 
     , m_color(color) 
     , m_price(price) 
    {} 
} 

class Apple : Fruit { 
    int m_apple_specific; 
    public: 
    Apple(int weight, int color, int price, int apple_specific) 
     : Fruit(weight, color, price) 
     , m_apple_specific(apple_specific) 
    {} 
} 

class Pear : Fruit { 
    int m_pear_specific; 
    public: 
    Apple(int weight, int color, int price, int pear_specific) 
     : Fruit(weight, color, price) 
     , m_pear_specific(pear_specific) 
    {} 
} 

[...] 

static Fruit parseFruit(InputData input) { 
    Fruit parsed_fruit; 
    if (input.name == 'apple') 
    parsed_fruit = Apple(input.weight, input.color, input.price, input.apple_specific); 
    else if (input.name == 'pear') 
    parsed_fruit = Pear(input.weight, input.color, input.price, input.pear_specific); 
    return parsed_fruit 
} 

は、次のサンプルコードを考えてみましょう。今、私はこのコードに2つの懸念があります:

  • 私がすでに嫌いなのは、それぞれの子クラスごとに基本クラスのコンストラクタを複製する必要があるということです(実際のコードでは、 )。これは簡単な方法ですか?
  • 本当に私はより洗練されたソリューションを求めています:メンバーを追加したいと考えていますm_originFruit ...すべてのサブクラスを調整する必要があります。

これは本当にそれが意味する方法ですか、それとも完全に間違ったアプローチですか?

P.S.入力データが常に便利な "InputData"オブジェクトにあると仮定しないでください(おそらく私のFruitコンストラクタを再設計することができます)が、Apple()またはPear()コンストラクタを直接使用することがあります。

struct FruitParams { 
    int weight; 
    int colour; 
    int price; 
}; 

class Fruit { 
    public: 
    explicit Fruit(FruitParams params) 
     : weight_(params.weight) 
     , colour_(params.colour) 
     , price_(params.price) {} 

    // ... 
}; 

ます。また、オプションのクラスAを行うことができます。また、あなたのケースを助け

+0

あなたの 'parseFruit'関数は機能しません。多相の階層を値で渡すことはできません。 –

+0

'parseFruit'はあなたの貧しい果物をスライスします。 – aschepler

+1

@aschepler:スライスされたリンゴは実際には本当に素晴らしいです。彼らは非常にフルーティーな味がする。 –

答えて

2

A一般的なガイドラインは、コンストラクタはあまりにも多くのパラメータを取得するたびに、あなたはおそらく別の「オプション」クラスをしたいということですメンバータイプ(Fruit::Params)。

その後、すべての派生コンストラクタ以下、シンプルな形を取る:

基底クラスへの変更は、現在すべてのに必要とせずに、一つの場所、すなわち、基底クラスのコンストラクタとそのオプションクラスで行うことができます
class Apple : public Fruit { 
    int apple_specific_; 

public: 
    Apple(FruitParams params, int a) : Fruit(params), apple_specific_(a) {} 
}; 

すべての派生クラスに触れてください。

関連する問題