使用更多参数覆盖虚函数

Override virtual function with more parameters

我有一群快乐的人。 每个快乐的人都有一个名为 updateHappiness() 的虚函数,用于更新他们的快乐属性。 每个人都喜欢自己的东西。

爱雨者是快乐的人,他们真的很喜欢听雨声,雨声会增加他们的幸福感。他们继承了快乐的人class。

因此,他们需要知道何时下雨,同时通过使用 updateHappiness(bool isRaining) 重载 updateHappiness() 函数来更新他们的幸福度,如 post 中所示:overload virtual function with different parameters in c++,但是,这是一个问题,因为有很多种人,我们想通过为每个人调用相同的函数来更新它们。

我们可以将参数存储在人体内 class 并将其传递到 class 构造函数中,就像在 post 中一样: Override number of parameters of pure virtual functions 然而雨不是雨恒定状态,我们将不得不调用函数 updateRainState(bool isRaining),这会导致与以前相同的问题。

我们可以将参数 bool isRaining 传递给每个人,即使他们不关心下雨,但这也会成为一个问题,因为有些人喜欢下雨,有些人喜欢看日光,有些人喜欢它当他们的朋友高兴时...所以它会添加许多无用的参数并且看起来很浪费。

最后,我能想到的最好的解决方案是在天气中有一个静态函数 class 来获取雨状态而不将其作为参数传递,但它看起来像一个全局变量,有些人说真的很烂!

你会怎样解决这个问题?

这是 classes 的示例代码:

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();
    }
}

您应该考虑采用完全不同的方法 - 改用事件回调。

当某些特定内容发生变化时,只有感兴趣的人会受到影响,因此您不应浪费时间和效果试图将更改传递给其他人。

如果一个人的幸福取决于天气,那么让这个人注册天气变化事件。 如果一个人的幸福取决于另一个人的幸福,那么让这个人注册另一个人的幸福变化事件。

以此类推

例如:

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();

    ...
}