【问题标题】:Both const and non-const version of the same function - an anti-pattern?同一函数的 const 和非 const 版本 - 反模式?
【发布时间】:2015-10-23 18:34:05
【问题描述】:

最近我检查了大量遗留的 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();
}

【问题讨论】:

  • const_cast const-correctness欺骗。它告诉编译器让你做一些它不能证明是正确的事情。
  • 有两个具有相同名称的成员函数,一个 const 另一个不具有 个合法用途,例如 beginend 迭代器函数,它们在非 const 对象上返回非 const 迭代器,在 const 对象上返回 const 迭代器,但如果它是从 const 强制转换来做某事,它闻起来像鱼。
  • 经典例子是operator [ ]en.cppreference.com/w/cpp/container/vector/operator_at的重载

标签: c++ constants anti-patterns


【解决方案1】:

不,不是总是。

这种模式有合法用途。例如,假设您正在编写一个集合,并且用于检索元素的代码相当复杂(例如哈希表)。您不想复制所有代码,但也希望您的集合能够同时用作 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)
        );
    }
};

在这里,const_cast&lt;&gt; 并不是真正的谎言。由于您的函数不是const,因此您知道只有当this 指向的对象也是非常量时才能调用它。因此,抛弃 constness 是有效的。

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

【讨论】:

  • 但是当你有 const 版本做事情和 non-const 时,最有可能应该用 tou 指向的方式来实现,它调用 const.
  • @Lol4t0 是的,可能。
  • 这个例子肯定是一个反模式。 “复杂代码”应该在 const 方法中。
  • @RichardHodges 不是在我的例子中吗?
  • ...否则,如果调用 true const 对象的非 const 函数并更改对象,您可能会鼓励未定义的行为
猜你喜欢
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多