我有一个类似于以下的类设计:
class MyClass {
public:
bool IsValid() const;
void MakeValid();
private:
bool CheckValidity(bool fix);
};
bool MyClass::IsValid() const {
// Check validity, but don't fix any problems found. Doesn't work.
return CheckValidity(false);
}
void MyClass::MakeValid() {
// Check validity and fix problems found.
CheckValidity(true);
}
IsValid
应该是const
,因为它不会进行更改。 MakeValid
应该为非常量,因为它确实进行了更改。它们共享相同的实现CheckValidity
,但是由于CheckValidity
可能会或可能不会进行更改,因此无法将其标记为const
。处理此问题的最佳方法是什么?最简单的方法是只使用
const_cast
,但是抛弃const会有点脏:bool MyClass::IsValid() const {
// Check validity, but don't fix any problems found.
return const_cast<MyClass*>(this)->CheckValidity(false);
}
这是对
const_cast
的合法使用吗?有没有更好的方法? 最佳答案
我假设您的实现与此类似:
bool CheckValidity(bool fix)
{
// Actually check validity.
bool isValid = ...;
if (!isValid && fix)
{
// Attempt to fix validity (and update isValid).
isValid = ...;
}
return isValid;
}
您确实将两种不同的功能合为一体。这种纠缠的关键指标之一是该函数的 bool 参数...之所以发出气味,是因为调用者在不引用代码/文档的情况下无法立即辨别是真还是假。
拆分方法:
bool CheckValidity() const
{
// Actually check validity.
bool isValid = ...;
return isValid;
}
void FixValidity()
{
// Attempt to fix validity.
// ...
}
然后,您的公共(public)方法可以使调用更加适当。
bool IsValid() const
{
// No problem: const method calling const method
return CheckValidity();
}
void MakeValid()
{
if (!CheckValidity()) // No problem: non-const calling const
{
FixValidity(); // No problem: non-const calling non-const
}
}