正确使用const_cast<>

时间:2010-04-20 08:02:30

标签: c++ const-cast

作为一项通用规则,在C ++代码中使用const_cast<>()通常被认为是一种不好的做法,因为它(大多数情况下)揭示了设计中的一个缺陷。

虽然我完全同意这一点,但我想知道使用const_cast<>() ok 唯一解决方案的案例是什么。

你们能告诉我你遇到的一些例子吗?

非常感谢。

8 个答案:

答案 0 :(得分:26)

它几乎被设计为仅用于非常规正确的旧API,即具有无法更改的具有非const接口但实际上不会在接口上改变任何内容的函数

答案 1 :(得分:18)

就像其他人所说的那样,它的主要目的是从对象中删除const,以便传递给你知道不会修改参数的非const正确函数。

有一个技巧(由迈耶斯?)来避免代码重复,它是这样的:

struct foo
{
    const return_type& get(void) const
    {
        // fancy pants code that you definitely
        // don't want to repeat

        return theValue; // and got it
    }

    return_type& get(void)
    {
        // well-defined: Add const to *this,
        // call the const version, then
        // const-cast to remove const (because
        // *this is non-const, this is ok)
        return const_cast<return_type&>(static_cast<const foo&>(*this).get());
    }
};

答案 2 :(得分:17)

const_cast也用于删除volatile修饰符,正如此(有争议的)文章中付诸实践:

http://www.drdobbs.com/184403766

答案 3 :(得分:10)

我同意你的陈述,正常使用是因为你需要隐藏'设计缺陷'。

IME典型的使用场景之一是当您尝试将C ++与现有C代码连接时。许多现有的C代码将C字符串作为char *,即使字符串未被修改,而它们通常表示为在C ++中转换为const char *的东西。这是通常使用const_cast解决的两种语言之间的阻抗不匹配。当然,您最好非常确保您与之交互的代码没有任何关于修改传入数据的可爱想法。

我会说这是代码在新编写的代码中有气味,但是为了与旧的C和C ++代码接口,这是一个必要的恶魔。也就是说,我会非常警惕任何非POD对象需要const_cast的代码,因为这通常是一个应该在设计级而不是代码级解决的问题。

答案 4 :(得分:4)

一个合法用途(在我看来)是std::set迭代器。它们始终为const,以防止更改集合中使用的密钥。更改密钥会破坏集合的内部结构并导致未定义的行为。

但是,只要密钥没有改变,就可以安全地更改对象中的其他数据。

假设你有std::set这样:

std::set<MyObject> some_set;

这样的课程:

class MyObject {
    public:
        MyObject(const std::string &key)
            : key_(key) {}

        bool operator<(const MyObject &other) const {
            return key_ < other.key_;
        }

    private:
        // ...
        // <some other data>
        // ...

        const std::string key_;
};

在上面的示例中,键已经是const ,因此即使您修改了对象,也无法破坏集合的内部结构。

通常,您只能从set迭代器中获取const引用:

const MyObject &object = *some_set_iterator;

但由于密钥为const,因此const_cast解除引用的迭代器是安全的:

MyObject &object = const_cast<MyObject &>(*some_set_iterator);

答案 5 :(得分:2)

一个非常合理的用法是当你同时拥有const和非const api(分别用于const和非const对象)时,如

class Bar {
   const SomeType& foo() const; 
   SomeType& foo();
}

然后,由于我们不想在两个函数中复制代码,我们经常使用

class Bar {
   SomeType& foo() {
      //Actual implementation 
   }
   const SomeType& foo() const {
        return const_cast<Bar*>(this)->foo();
   }
};

这当然是假设foo没有做违反const语义的事情。

答案 6 :(得分:0)

是的,当然,当您的调用代码无法修改且不正确时。应该注意的是,您只应该使用它来调用您知道的函数,这些函数不会修改您的数据!

答案 7 :(得分:0)

c ++入门(第5版)书中有一个const_cast用法示例。 下面的函数返回对常量字符串的引用

// return a reference to the shorter of two strings
const string &shorterString(const string &s1, const string
&s2)
{
    return s1.size() <= s2.size() ? s1 : s2;
}

这本书然后提到了当我们需要非const引用时的情况。

  

我们可以在一对非常量字符串参数上调用该函数,但是   我们将获得对const字符串的引用作为结果。我们可能想要   具有shortString的版本,当给定非常量时   参数,将产生一个简单的参考。我们可以写这个版本的   我们使用const_cast的函数:

string &shorterString(string &s1, string &s2)
{
    auto &r = shorterString(const_cast<const string&>(s1),
                            const_cast<const string&>(s2));
    return const_cast<string&>(r);
}
  

此版本通过强制转换为shortString的const版本   引用const的参数。该函数返回对   一个const字符串,我们知道它绑定到我们的原始字符串之一,   非常量参数。因此,我们知道强制转换该字符串   返回纯字符串&。

根据该书,如果我们知道可以安全投放,则应使用该书。