[英]How to define `health` and `maxHealth` in one object, when `healt` can't be higher than `maxHealth`?
我有一個名為Warrior
的類,它具有uint m_health
和uint m_maxHealth
屬性。 我希望我的構造函數采用參數Warrior(uint health, uint maxHealth)
。
現在我已經學習了很多C ++並且我知道所有的語法等,但是很難找到關於如何使用這些東西等的教程。所以我真的不知道如何定義health
和maxHealth
當health
顯然不能高於maxHealth
:/
以下是我想到的幾種方法:
// method 1
Warrior::Warrior(uint health, uint maxHealth) :
m_health((health > maxHealth) ? maxHealth : health),
m_maxHealth(maxHealth)
{}
// method 2
Warrior::Warrior(uint health, uint maxHealth) :
m_maxHealth(maxHealth)
{
if (health > maxHealth) {
m_health = maxHealth;
}
else {
m_health = health;
}
}
我相信還有其他方法。 很抱歉,如果這只是一個意見問題,但如果在C ++中有一種“首選”方式,它會是什么?
如果你打算在游戲中設置健康狀況,你可能需要考慮這樣的事情:
Warrior::Warrior(unsigned int health, unsigned int maxHealth) :
m_maxHealth(maxHealth)
{
setHealth(health);
}
void Warrior::setHealth(unsigned int health)
{
m_health = std::min(health, m_maxHealth);
}
根據您對更好的定義,有一種“更好”的方式。 (我猜你的意思是“更短”)
Warrior::Warrior(unsigned int health, unsigned int maxHealth) :
m_health(std::min(health, maxHealth)),
m_maxHealth(maxHealth)
{
}
這實際上是關於界面設計的問題,而不是實際的實現。 代碼中的兩個實現都是類似的,並且實現了一個具有寬接口的設計,允許任何參數組合。
另一種方法是在構造函數上使用窄契約,其中只有在health < maxHealth
為真的明顯約束時才能很好地定義對象的行為。 在這種情況下,您將記錄構造函數並實現它:
Warrior::Warrior(unsigned int health, unsigned int maxHealth)
: m_health(health), m_maxHealth(maxHealth)
{
assert(health <= maxHealth);
}
在我看來,這是一個更好的設計。 沒有充分的理由接受構造函數的錯誤參數。 通過在那里添加assert
,您可以在開發周期的早期檢測到您的類型是否在合同之外使用。 這對於具有相同類型的多個參數的函數尤為重要,因為它有助於檢測是否錯誤地將參數無序傳遞。 在那里使用廣泛的合同會使maxHealth
與當前的health
相同,並且稍后你會在試圖弄清楚Warrior
為什么比你認為的那樣弱的時候遇到問題... 狹窄的合同會立刻告訴你參數亂序。
template <typename T>
class RangeBoundValue
{
public:
RangeBoundValue(const T _min, const T _max) : _min(_min), _max(_max) {}
void setValue(T val)
{
if (val < _min) _value = _min;
else if (val > _max) _value = _max;
else _value = val;
}
T value() const {return _value;}
private:
const T _min;
const T _max;
T _value;
};
在Warrior
使用這個助手類
class Warrior
{
...
private:
RangeBoundValue<uint> _health;
};
我會在不滿足前提條件的情況下放置斷言或拋出異常:
Warrior::Warrior(uint health, uint maxHealth) :
m_health(health),
m_maxHealth(maxHealth)
{
assert(health <= maxHealth);
// or throw exception
throw std::logic_error("explanation");
}
我的意思是,決定呼叫者的理性是什么? 如果調用者將健康值設置為大於maxHealth - 它違反了您的類邏輯,那么我建議立即失敗並通知調用者。 它應該是軟件中的問題,所以我認為隱藏它是不可取的。
異常或斷言是一種明確的機制,可以幫助您盡早發現並識別此類問題。
我很驚訝當構造函數的參數列表提供了health> max_health時,人們建議拋出異常。 例如,假設您有一些復活實施,其中所有生物都恢復了固定的生命值,直到最大生命值,並且在某些情況下這超過了最大生命值,為避免耦合,您不希望此方法必須存儲每個對象的最大的健康狀況,您可以在將這些參數提交給構造函數之前添加測試它的方法,但這又會使事情變得復雜。 最大健康通常被實施為健康上限,並且鑒於這是一個簡單的約束,與其他任何事物脫鈎,應該是戰士有責任強制執行自己的約束。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.