1

看着这个答案,我知道你不应该像我在我的程序中那样使用 C++ 中的友谊来复制私有指针:

class bar;

class foo
{
private:
   some_smart_pointer<int> state;

public:
   foo(int value) : state(new int(value)) {}
   friend class baz;
};

class bar
{
private:
   some_weak_pointer<int> state;
public:
   friend class baz;
};

class baz
{
public:
   foo Foo;
   bar Bar;

   baz() { Bar.state = Foo.state; }
};

没关系,但是传递一个常量智能指针违反了封装原则。
它暴露了系统的内部。将 bar 传递给 foo 也会产生耦合。同样在我的系统中,将对象聚合到该问题中所谓的流畅界面是有意义的:

MainObject.PropertyCollection.Property

正如在那个 SO 答案中所说的那样,它不违反得墨忒耳定律,还是吗?
我在这里非常困惑。
我正在最后一次重新设计我的图书馆,我希望它是正确的。
我认为与其传递我的内部智能指针,不如传递一个包装类,该类也将用作属性并将其设置为只读,然后复制是安全的,对吧?

根据评论进行编辑:嗯,我正在实施 D20 3.5 SRD ( http://www.d20srd.org/ )。
例如,有六种能力。
在我的设计中,D20Abilities 聚合在 D20Character 中。
D20Abilities 包含 6 个 D20Ability 实例:力量、敏捷、体质。智慧、智慧和魅力。
所有 D20Ability 实例都拥有一个在整个系统中共享的私有状态(称为修饰符)。例如,每个技能都需要自己的技能修饰符。

4

1 回答 1

2

关于你的描述和得墨忒耳法则。使用来自维基百科的示例,据说更喜欢:

void exercise(const Dog& d) { return d.walk(); }

代替:

void exercise(const Dog& d) { return d.legs.move(); }

因为狗应该知道如何走路而不是四处移动。将此应用于您的 D&D 计划,我们会得到类似的东西,而不是:

bool hit_orc_with_long_sword(const Character& c, int DCValue) {
   return c.D20Abilities.Strength() + d20.roll() > DCValue;
}

首选:skill_check(c, MeleeAttack(LongSword(), Orc());

bool skill_check(const Character& c, const Action& a) {
    return c.attempt(a);
}

//.... in class character:

bool Character::attempt(const Action& a)
{
    return a.check_against(D20Abilities);
}

//.... in class Action:

bool Action::check_against(const D20Abilities& a) {
   return GetRelevantStat(a) + d20.roll() > DCValue;
}

这样,角色无需通过属性组进行访问,而是知道如何执行动作,而动作则知道他们在某些统计数据上成功的可能性有多大。它解耦了接口。消费者代码(如上面的 hit_orc_with_long_sword )不必“告诉”角色如何检查他的力量,它由类的交互处理,每个类都处理一个定义明确的域。

但是,提供的代码示例看起来确实存在一些问题。当您使用朋友做任何事情而不是实现某些运算符时,我发现它指向一个设计问题。您不应该将内部状态从一个对象扔到另一个对象;对象应该知道如何从它们自己的内部状态以及作为函数传递给它们的参数执行一组动作。

于 2009-06-15T04:58:06.697 回答