C++多变量安全封装疑问:Blackjack游戏OOP重构是否需用Getter/Setter
Blackjack游戏C++面向对象重构:Getter/Setter的必要性与重构思路
问题背景
我正在把自己的Blackjack游戏用C++重构成面向对象风格,知道出于安全性和封装性考虑,类成员变量不应设为public,若需访问应实现Getter和Setter方法。但问题是main.cpp里频繁使用这些变量,且变量数量多,逐一实现Getter/Setter太繁琐。
现有类代码片段
Account类
class Account { private: std::fstream saveFile; public: std::string name; int tokenAmount, betAmount; bool doubledDown, splitted; bool canDoubleDown, canSplit; int choseToStand; void registerUser(); void saveBalance(); // [...] (constructor) };
Hand类
class Hand { public: std::vector<std::pair<std::string, std::string>> cards; std::pair<bool, bool> handBusted; int cardSum; void display(); int sum(); bool checkForBj(); };
main.cpp中直接操作类变量的代码
std::cout << "Decision: [1] Stand, [2] Hit"; if (!player.splitted && !player.doubledDown && roundNumber == 1 && player.betAmount <= player.tokenAmount) { std::cout << ", [3] Double down"; player.canDoubleDown = true; }
如果替换成Getter/Setter调用,代码会变得难以阅读,想咨询:
- 在此场景下是否有必要实现Getter和Setter?
- 若有必要,是否必须重写现有代码?
解答
1. 不是必须为所有变量写Getter/Setter
OOP的核心是封装行为而非单纯封装变量,不要为了“符合规范”而机械地给每个public变量加Getter/Setter。当前代码的问题不是变量暴露本身,而是业务逻辑散落在main函数中,类只充当了状态的容器,没有承担起对应的行为职责。
2. 正确的重构方向:把业务逻辑内聚到类中
与其硬写一堆Getter/Setter,不如把原本在main里的逻辑移到类的成员函数中,让类自己管理状态和行为:
- 比如判断是否允许Double Down的逻辑,完全可以封装成
Account类的成员函数:
这样class Account { private: // 把所有状态变量设为private std::fstream saveFile; std::string name; int tokenAmount, betAmount; bool doubledDown, splitted; bool canDoubleDown, canSplit; int choseToStand; public: // 封装判断逻辑 bool isEligibleForDoubleDown(int roundNumber) const { return !splitted && !doubledDown && roundNumber == 1 && betAmount <= tokenAmount; } // 提供行为方法,而非直接修改变量 void enableDoubleDown() { canDoubleDown = true; } // 其他原有方法和必要的Getter/Setter std::string getName() const { return name; } void setBetAmount(int amount) { // 可以在这里加校验逻辑,比如不能超过tokenAmount if (amount > 0 && amount <= tokenAmount) { betAmount = amount; } } // [...] };main里的代码就可以简化为:std::cout << "Decision: [1] Stand, [2] Hit"; if (player.isEligibleForDoubleDown(roundNumber)) { std::cout << ", [3] Double down"; player.enableDoubleDown(); } - 对于
Hand类,同样可以把cards设为private,提供addCard()、getCardCount()等方法,而不是直接暴露vector;cardSum可以通过sum()方法获取,不需要直接暴露变量。
3. 何时需要Getter/Setter?
只有当外部确实需要读取某个状态,且该状态无法通过类的行为方法获取时,才需要写Getter;Setter同理,只有当外部需要修改状态,但必须经过类的校验或逻辑处理时,才需要写Setter(比如修改betAmount时检查合法性)。
4. 要不要重写现有代码?
要,但不是机械替换成Getter/Setter,而是重构逻辑,将业务行为内聚到类中。这样做的好处是:
- 类的内部状态更安全,不会被外部随意修改导致逻辑混乱;
- 业务逻辑集中在类中,后续维护、修改规则(比如调整Double Down的条件)时,只需要修改类的代码,不需要在
main里到处找相关逻辑; main函数会更简洁,只负责处理用户交互和流程控制,代码可读性反而会提升。
内容的提问来源于stack exchange,提问作者dheb
相关产品推荐
相关产品推荐

