2016-07-22 3 views
-2

私は幸せな人の配列を持っています。 それぞれの幸せな人物には、そのhappyiness属性を更新するために使用されるupdateHappiness()という仮想関数があります。 各人は自分のことが好きです。より多くのパラメータで仮想関数を上書きする

雨の好きな人は、雨の音が聞こえて幸せな人で、幸福度を高めます。彼らは幸せな人のクラスから継承します。

結果として、この投稿のようにupdateHappiness(bool isRaining)でupdateHappiness()関数をオーバーロードすることで、幸せを更新しながら雨が降っているかどうかを知る必要があります:overload virtual function with different parameters in c++しかし、私たちはすべての人に同じ機能を呼び出すことでそれらをすべて更新したいと考えています。

このポストのように、パラメータをPersonクラスの内部に格納してクラスコンストラクタに渡すことができます:Override number of parameters of pure virtual functionsしかし、rainは一定の状態ではなく、関数updateRainState(bool isRaining)を呼び出す必要があります。前と同じ問題が発生します。

雨が気にならないにもかかわらず、すべての人にパラメータbool isRainingを渡すことができましたが、雨のような人や昼間のような人々、彼らの友達は幸せです...それは多くの無駄なパラメータを追加し、それは無駄に思われます。

最後に、私が考えることができる最良の解決策は、パラメータとして渡さずに雨の状態を取得するために天気のクラスに静的関数を持たせることですが、グローバル変数のように見えます。悪い!

この問題を解決するにはどうすればよいですか?代わりに、イベントコールバックを使用する - あなたは完全に異なるアプローチを取って検討すべきである

class HappyPerson 
{ 
public: 
    HappyPerson(): m_happinness(0) {} 
    virtual void updateHappinness() { m_happinness++; } 

protected: 
    int m_happinness; 
}; 

class Weather 
{ 
public: 
    static int isRaining() { return raining; } 

private: 
    static bool raining; 
}; 

bool Weather::raining(0); 

class RainLover : public HappyPerson 
{ 
public: 
    RainLover() : HappyPerson() {} 
    void updateHappinness() { m_happinness++; if (Weather::isRaining()) m_happinness++; } 
}; 

int main() 
{ 
    std::vector<HappyPerson*> happyPeople; 
    happyPeople.push_back(new RainLover); 

    // ... add many other persons 

    std::vector<HappyPerson*>::iterator it; 
    for (it = happyPeople.begin(); it != happyPeople.end(); it++) 
    { 
     (*it)->updateHappinness(); 
    } 
} 
+0

確かに、これらの人々は、生のポインタとしてコンテナに格納されているとは限りません。代わりに 'std :: vector >'を使用してください。 – ArchbishopOfBanterbury

+0

あなたのアプリケーションのコンテキストでは、「HappyPerson」が天気を知っていることは意味がありますか?天気に興味のある人は、Weather通知に変更があったときに通知を受信して​​、興味のある天気の天気を照会することができます。 –

+0

これは単なる例ですが、彼らはまだ心配していません。多形性を有効にするためにいくつかのポインタを使用しなければならなかった – MaxV37

答えて

2

:ここ

は、クラスのようなもので何のコード例です。

特に何かが変更された場合、関心のある人だけが影響を受けるため、変更を他の人に引き継ぐために時間と労力を費やすべきではありません。

人の幸せが天気に左右される場合は、天気の変化のイベントに登録するようにしてください。 人の幸福が他の人の幸福に依存する場合、その人に他の人の幸福変化イベントに登録させる。

など。

class HappyPerson; 

class HappinessChangeListener 
{ 
public: 
    void happinessChanged(HappyPerson *person, bool isHappier) = 0; 
}; 

class HappyPerson 
{ 
public: 
    HappyPerson(); 
    virtual ~HappyPerson() {} 

    void updateHappiness(int amount); 

    void registerHappinessChangeListener(HappinessChangeListener *listener); 
    void unregisterHappinessChangeListener(HappinessChangeListener *listener); 
); 

protected: 
    int m_happinness; 
    std::vector<HappinessChangeListener*> happinessChangeListeners; 

    void happinessChanged(bool isHappier); 
}; 

... 

HappyPerson::HappyPerson() 
    : m_happinness(0) 
{ 
} 

void HappyPerson::updateHappiness(int amount) 
{ 
    if (amount != 0) 
    { 
     m_happinness += amount; 
     happinessChanged(amount > 0); 
    } 
} 

void HappyPerson::registerHappinessChangeListener(HappinessChangeListener *listener) 
{ 
    happinessChangeListeners.push_back(listener); 
} 

void HappyPerson::unregisterHappinessChangeListener(HappinessChangeListener *listener) 
{ 
    std::vector<HappinessChangeListener*>::iterator i = std::find(happinessChangeListeners.begin(), happinessChangeListeners.end(), listener); 
    if (i != happinessChangeListeners.end()) 
     happinessChangeListeners.erase(i); 
} 

void HappyPerson::happinessChanged(bool isHappier) 
{ 
    for(std::vector<HappinessChangeListener*>::iterator i = happinessChangeListeners.begin(); i != happinessChangeListeners.end(); ++i) 
     i->happinessChanged(this, isHappier); 
} 

class Weather; 

class WeatherChangeListener 
{ 
public: 
    void weatherChanged(Weather *weather) = 0; 
}; 

class Weather 
{ 
public: 
    Weather(); 

    void rainStarted(); 
    void rainStopped(); 
    bool isRaining(); 

    void registerWeatherChangeListener(WeatherChangeListener *listener); 
    void unregisterWeatherChangeListener(WeatherChangeListener *listener); 

protected: 
    bool m_raining; 
    std::vector<WeatherChangeListener*> weatherChangeListeners; 

    void weatherChanged(); 
}; 

... 

Weather::Weather() 
    : m_raining(false) 
{ 
} 

void Weather::rainStarted() 
{ 
    if (!m_rRaining) 
    { 
     m_rRaining = true; 
     weatherChanged(); 
    } 
} 

void Weather::rainStopped() 
{ 
    if (m_rRaining) 
    { 
     m_rRaining = false; 
     weatherChanged(); 
    } 
} 

bool Weather::isRaining() 
{ 
    return m_raining; 
} 

void Weather::registerWeatherChangeListener(WeatherChangeListener *listener) 
{ 
    weatherChangeListeners.push_back(listener); 
} 

void Weather::unregisterWeatherChangeListener(WeatherChangeListener *listener) 
{ 
    std::vector<WeatherChangeListener*>::iterator i = std::find(weatherChangeListeners.begin(), weatherChangeListeners.end(), listener); 
    if (i != weatherChangeListeners.end()) 
     weatherChangeListeners.erase(i); 
} 

void Weather::weatherChanged() 
{ 
    for(std::vector<WeatherChangeListener*>::iterator i = weatherChangeListeners.begin(); i != weatherChangeListeners.end(); ++i) 
     i->weatherChanged(this); 
} 

class RainLover : public HappyPerson, public WeatherChangeListener 
{ 
public: 
    RainLover(std::shared_ptr<Weather> &weather); 
    ~RainLover(); 

    void weatherChanged(Weather *weather); 

protected: 
    std::shared_ptr<Weather> m_weather; 
}; 

... 

RainLover::RainLover(std::shared_ptr<Weather> &weather) 
    : HappyPerson(), m_weather(weather) 
{ 
    m_weather->registerWeatherChangeListener(this); 
} 

RainLover::~RainLover() 
{ 
    m_weather->unregisterWeatherChangeListener(this); 
} 

void RainLover::weatherChanged(Weather *weather) 
{ 
    updateHappiness(weather->isRaining() ? 1 : -1); 
} 

class HappyLover : public HappyPerson, public HappinessChangeListener 
{ 
public: 
    HappyLover(std::shared_ptr<HappyPerson> &person); 
    ~HappyLover(); 

    void happinessChanged(HappyPerson *person, bool isHappier); 

protected: 
    std::shared_ptr<HappyPerson> m_person; 
}; 

... 

HappyLover::HappyLover(std::shared_ptr<HappyPerson> &person) 
    : HappyPerson(), m_person(person) 
{ 
    m_person->registerHappinessChangeListener(this); 
} 

HappyLover::~HappyLover() 
{ 
    m_person->unregisterHappinessChangeListener(this); 
} 

void HappyLover::happinessChanged(HappyPerson *person, bool isHappier) 
{ 
    updateHappiness(isHappier ? 1 : -1); 
} 

:例えば

int main() 
{ 
    std::shared_ptr<Weather> weather(new Weather); 
    std::vector<std::shared_ptr<HappyPerson>> happyPeople; 

    happyPeople.push_back(std::shared_ptr<HappyPerson>(new RainLover(weather))); 
    // or: happyPeople.push_back(std::make_shared<RainLover>(weather)); 

    happyPeople.push_back(std::shared_ptr<HappyPerson>(new HappyLover(happyPeople[0]))); 
    // or: happyPeople.push_back(std::make_shared_ptr<HappyLover>(happyPeople[0])); 

    // ... add many other persons 

    weather->rainStarted(); 
    ... 
    weather->rainStopped(); 

    ... 
} 
+0

ありがとう、本当に助かりました – MaxV37

関連する問題