const和非const版本的功能相同 - 反模式?

RX_*_*_RX 4 c++ anti-patterns const

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

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

    void Bar() const 
    {
        const_cast<Foo*>(this)->Bar(); 
    }
};
Run Code Online (Sandbox Code Playgroud)

这是一个巨大的反模式吗?我的意思是,函数是const还是非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();
}
Run Code Online (Sandbox Code Playgroud)

The*_*ant 7

不,不总是.

这种模式有合法用途.例如,假设您正在编写集合,并且用于检索元素的代码相当复杂(例如,哈希表).您不希望复制所有代码,但您还希望您的集合能够用作const和非const.

所以,你可能会这样做:

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)
        );
    }
};
Run Code Online (Sandbox Code Playgroud)

在这里,这const_cast<>不是一个谎言.由于你的函数是非函数const,你知道只有当指向的对象this也是非const时才能调用它.因此,抛弃常数是有效的.

(当然,类似于这种情况,你可以const通过抛弃实例的const-ness 来调用非方法const,但是在那时它是你的类的用户已经引入了未定义的行为,所以你只要覆盖你的班级正确使用.)