同一函数的 const 和非 const 版本 - 反模式?

Both const and non-const version of the same function - an anti-pattern?

最近我检查了大量遗留 C++ 代码,发现了一些我以前从未在生产 C++ 代码中见过的东西:

class Foo
{
public:
    void Bar()
    {
        std::cout << "Hello from Bar()!" << std::endl;
    }

    void Bar() const 
    {
        const_cast<Foo*>(this)->Bar(); 
    }
};

这是一个巨大的反模式吗?我的意思是,该函数要么是 const 要么是非常量,提供两个版本有什么意义?这是某种 'const-correctness cheat',允许调用 const 函数的情况是这样的:

void InvokeBar(const Foo& foo)
{
    // oh boy! I really need to invoke a non-const function on a const reference!
    foo.Bar();
}

不,不是 总是。

此模式有合法用途。例如,假设您正在编写一个集合,并且用于检索元素的代码相当复杂(例如哈希 table)。您不想复制所有代码,但您也希望您的集合能够用作常量和非常量。

所以,您可以这样做:

struct HashTable {
    ...

    const Value &get(Key key) const {
        ... complex code for retrieving the key
    }

    Value &get(Key key) {
        return const_cast<Value &>(
            static_cast<const HashTable *>(this)->get(key)
        );
    }
};

在这里,const_cast<>并不是真的在撒谎。由于您的函数是非 const,您知道只有当 this 指向的对象也是非常量时才能调用它。因此,抛开 constness 是有效的。

(当然,与这种情况类似,您可以通过丢弃 const 实例的 const-ness 来调用非 const 方法,但此时它是你的 class 的用户,他已经引入了未定义的行为,因此只要你的 class 被正确使用,你就会被覆盖。)