【问题标题】:Override virtual function with more parameters用更多参数覆盖虚函数
【发布时间】:2016-11-26 21:36:42
【问题描述】:

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

爱雨的人是快乐的人,他们真的很喜欢听雨声,这会增加他们的幸福感。它们继承自快乐的人类。

因此,他们需要知道什么时候下雨,同时通过使用 updateHappiness(bool isRaining) 重载 updateHappiness() 函数来更新他们的幸福感,就像在这篇文章中一样:overload virtual function with different parameters in c++,但是,这是一个问题,因为有各种各样的人,我们希望通过为每个人调用相同的函数来更新他们。

我们可以将参数存储在 person 类中,并将其传递给类构造函数,如本文所述:Override number of parameters of pure virtual functions 但是下雨不是恒定状态,我们必须调用函数 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();
    }
}

【问题讨论】:

  • 有一点是肯定的,这些人不乐意将原始指针存储在容器中。请改用std::vector&lt;std::unique_ptr&lt;HappyPerson&gt;&gt;
  • 在您的应用程序上下文中,每个“HappyPerson”都知道天气是否有意义?对天气感兴趣的人可以注册以在天气通知发生变化时接收警报,以便他们可以查询他们感兴趣的天气方面......
  • 这只是一个例子,他们仍然很高兴不用担心。我必须使用一些指针才能使多态性生效
  • 不,每个人都对天气不感兴趣,他们可能对任何事情都感兴趣
  • @MaxV37:丹的观点仍然有效。您应该改用事件回调。当事情发生变化时,只有感兴趣的人会受到影响,无需浪费时间和影响将变化传递给每个人。如果一个人的幸福取决于天气,那么让该人注册天气变化事件。如果一个人的幸福取决于另一个人的幸福,那么让这个人注册另一个人的幸福变化事件。以此类推。

标签: c++ interface overloading virtual


【解决方案1】:

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

当某些特定的变化发生时,只有感兴趣的人会受到影响,所以你不应该浪费时间和效果试图将变化传递给其他人。

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

等等。

例如:

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

    ...
}

【讨论】:

    猜你喜欢
    • 2013-02-02
    • 2013-10-04
    • 2011-02-24
    • 2015-04-20
    • 2021-09-30
    • 2015-06-17
    • 2015-12-15
    • 2011-11-23
    • 2017-09-22
    相关资源
    最近更新 更多