在成员类之间进行通信的正确方法是什么?

时间:2015-04-14 08:27:35

标签: c++ object

我正在写一个RPG,基本代码如下。每个玩家应该有四个属性:地球,空气,火和水。问题在于:如果火少于零,它应该溢出到地球的损害。到目前为止,这是我的代码:

//DANCE GAME
#include <iostream>
using namespace std;

class element {
    public:
        //get primary magnitude
        int gpm(){
            return pm;
        };
        //set primary magnitude
        int spm(int x){
            pm = x;
        };
    protected:
        //primary magnitude
        int pm;
};

class fire : public element {
};

class earth : public element {
};

class soul {
    public:
        earth e;
        fire f;
};

int main () {
    soul p1, p2;

    p1.e.spm(5);
    cout << p1.e.gpm() << endl;

    p1.f.spm(5);
    cout << p1.f.gpm() << endl;

    return 0;
};

所以,我希望每个元素都有一个独特的spm()函数来控制它的特殊行为。对于火灾,它应该具有以下伪代码的效果:

fire.spm(int x)
    pm += x
    if pm < 0
        x = abs(pm)
        pm = 0
        owner.earth -= x

显然,最后一行是给我带来麻烦的。完成这样的事情的正确方法是什么?

3 个答案:

答案 0 :(得分:1)

您应该将所有者作为参数传递给方法spm。

答案 1 :(得分:1)

  

显然,最后一行给了我一些问题。完成这样的事情的正确方法是什么?

有一条指南说明您不应该使用其他对象的数据(Demeter法则)。相反,您应该将更改向下传播,从知道其他人的对象传播到只知道如何处理自己数据的对象。

这意味着您的fire元素实现不应该知道soul具有earth元素(更不用说尝试直接更改它)。相反,soul负责传播这些更改(因为soul实例同时知道earthfire类。

基于此,你应该考虑这样的事情:

class element
{
public:
    // update primary magnitude, taking hints from the provided element
    // if this->get_type() == other.get_type()
    // at the end of the operation, primary_magnitude_ should be 
    // other.primary_magnitude_;
    virtual void update(const element& other)
    {
        if(get_type() == other.get_type())
            set_magnitude(other.magnitude());
    }
protected:
    enum { earth_type, fire_type, air_type, water_type } element_type;
    virtual element_type get_type() const = 0;

    int magnitude() const { return primary_magnitude_; }
    void update_magnitude(int delta) { primary_magnitude_ += delta; }
    void set_magnitude(int value) { primary_magnitude_ = delta; }

private:

    int primary_magnitude_;
};

class earth
{
public:
    void update(const element& other) override
    {
        switch(other.get_type())
        {
        case element::earth_type:
            set_magnitude(other.magnitude());
            break;
        case element::fire_type:
            update_magnitude( std::min(0, other.magnitude()) );
            break;
        }
    }
protected:
    element_type get_type() const override { return element::earth_type; }
};

class soul
{
public:
    void update(const element& value)
    {
        earth_.update(value);
        fire_.update(value);
    }
private:
    earth earth_;
    fire fire_;
};

答案 2 :(得分:0)

spm表示&#34;设置主要幅度&#34;。关于此的两点说明。首先,如果函数应该实际设置主要幅度,则调用函数SetPrimaryMagnitudeset_primary_magnitude会更好。它让生活变得如此简单。顺便说一句,element类只有一个值pm,所以我不认为需要调用该值&#34; primary&#34;。我的意思是,什么是&#34;中学&#34;?

其次,您实际上并不想设置该值,而是将一系列动作组合起来,增加,减少并将差异溢出到另一个值。也许最好将此类行动称为“调整”#34;并使其成为soul的成员(如果该类是唯一以这种特定方式处理数学的类)。像这样:

soul::AdjustElementValues(element& primary, element& secondary, int value)
{
    // decrease primary by value, and if needed spill the remains to secondary
}

如果soul不是唯一进行此数学运算的类,则将数学运算到单独的类,该类可以访问所有需要的对象。比如,class element_spiller带有指向两个elements,主要和辅助的指针的构造函数,并且有一个方法可以获取int value参数并相应地更改elements