使用更多参数覆盖虚拟函数

时间:2016-07-22 21:41:35

标签: c++ interface overloading virtual

我有一群快乐的人。 每个快乐的人都有一个名为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();
    }
}

1 个答案:

答案 0 :(得分: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();

    ...
}