我有一个类似于以下的类设计:

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
    }
}

09-06 13:28