传递对象和面向对象的设计最佳实践

时间:2010-07-14 04:35:54

标签: c++ oop

我是一名大学生,学习编程。为了练习我正在写一个二十一点程序。我正在使用C ++并采用面向对象的方法。

我有一个Deck课程,它基本上可以构建和改组一副牌。生成的牌组由52个Card类对象组成。这就是我到目前为止所做的。

我的计划是拥有一个经销商对象,​​其中有一张52张牌的卡片将卡片交给第二个玩家对象,然后交易给经销商自己的手。

我的第一个问题是:在Deck类中公开Card对象数组是不好的做法?

我问这个是因为我认为数组是一个属性,并且教导大多数属性应该是私有的。我不想在我的项目中开始使用糟糕或懒惰的做法,并希望以正确的方式做到这一点。

另一个问题:对象(例如我的二十一点程序中使用的Card对象)通常如何从一个对象(如经销商)移动到第二个对象(如玩家)?

4 个答案:

答案 0 :(得分:3)

  

我的第一个问题是:在Deck类中公开Card对象数组是不好的做法?

是。通常,数据成员应始终是私有的。创建一个没有关联数据的接口是很好的OOP,它定义了可以对对象执行的操作,然后提供实现该接口的具体类。数据是一个实现细节,在界面中甚至在完全具体的类中都不应该是可见的。作为它为什么不好的一个例子,你现在可以使用一组Card对象来实现你的类,但是稍后你可能决定使用一个位集,其中一个位指示卡是否存在于卡中。如果您将Card数组对象公开,那么以这种方式更改表示将破坏您的类的其他用户;但是,如果您将其保密,则可以在不影响班级用户的情况下进行更改。

  

另一个问题:对象(例如我的二十一点程序中使用的Card对象)通常是如何从一个对象(如经销商)移动到第二个对象(如玩家)?

这取决于另一个对象是否需要访问原始卡对象,另一个对象是否会长时间或短时间保留原始对象,或者另一个对象是否只能处理副本的卡。它还取决于卡是具体类还是多态类型,因为多态对象只能通过指针或引用传递(因为按值传递多态对象将导致代码切片)。使用具体对象,除非需要修改或访问原始对象,否则可以选择传递副本,在这种情况下需要引用。选择正确的传递对象的方法有点复杂,但希望这将澄清:

如果符合以下条件,则按值传递:

它是一种原始类型或小型非多态混凝土类型,不需要修改。

通过常量引用 - 对于某种类型const T&T - 如果:

  1. 您无需修改​​原始对象。
  2. 您无需读取函数范围之外的原始对象。
  3. 您不需要读取超出函数范围或类型的对象 非多态和复制便宜,因此如果需要挂起,可以创建一个副本 它。
  4. 通过引用传递 - 对于某种类型T&T - 如果:

    1. 您需要修改原始对象。
    2. 您不需要在函数范围之外读取/写入原始对象。
    3. 您不需要读取超出函数范围或类型的对象 非多态和复制便宜,因此如果需要挂起,可以创建一个副本 它。
    4. 通过常量智能指针指向const - 某些类型为const shared_ptr<const T>& T - 如果:

      1. 您需要在函数范围内及以后阅读原始对象。
      2. 您需要在函数范围内及以后读取对象,并且类型是非多态的,因此无法安全地创建它的副本。
      3. 通过常量智能指针 - 某些类型const shared_ptr<T>&T - 如果:

        1. 您需要在函数范围内及以后读取和写入原始对象。
        2. 我已经按照故意的顺序给出了上述每一个;你应该尝试第一个足以完成工作的工作,如果前一个工作不够,则只能进入下一个工作。另外,我应该补充说boost::call_traits<T>::param_type可以帮助您在传递值和在具体的非多态类型的情况下通过常量引用进行选择(它可以根据对象的大小确定是否通过值传递或通过常量参考更好)。

答案 1 :(得分:1)

至少IMO,你试图过度。实际上,卡片组没有任何行为 - 它只是一堆卡片。你没有经销商告诉牌组自己洗牌;你有一个经销商谁洗牌。我也会在一个程序中做同样的事情 - 这个套牌只是一个由经销商拥有的std::vector<card>(它几乎肯定是私有的)。

对于交易,每个玩家手上都有自己的std::vector<card>。然后,经销商通过调用玩家的deal(或其他)成员函数,一次通过每个玩家一张牌。

答案 2 :(得分:0)

1)一般来说,是的。从概念上讲,播放器实例不会弄乱属于经销商的卡片,因此它应该是私有的。

2)一种方法:

struct Card
{
    Suit suit;
    Rank rank;
};

class Player
{
private:
    void AddCard(Card card);
    friend class Dealer;
};

class Dealer : public Player
{
public:
    void DealTo(Player& player);
};

Dealer dealer;
Player player2;
dealer.DealTo(player2);

答案 3 :(得分:0)

  

我的第一个问题是:在Deck类中公开Card对象数组是不好的做法?

取决于。但公开披露数据通常是不好的 这是因为公共项目成为界面的一部分,因此必须进行维护。

最好使数组成为私有成员,然后通过公共接口公开操作。这将允许您稍后更改私有数据(例如,当您学习如何使用向量时,您可以用向量替换该数组。如果该数组是公共的,您将无法更改类型而不会影响其他所有类型使用了这个事实,它是一个数组)。

原则:隐藏实施细节 这导致类型之间的耦合更加松散。

  

另一个问题:对象(例如我的二十一点程序中使用的Card对象)通常是如何从一个对象(如经销商)移动到第二个对象(如玩家)?

从一个对象中的数组中删除它(并收缩数组以显示它有更少的卡(因此您可能需要一个可以改变大小的容器类型))然后将它放入目标对象中的另一个数组(容器)