为什么const_cast需要说明你要投射的内容?

时间:2010-12-08 02:53:18

标签: c++ casting standards

根据标准(§5.2.11),const_cast会抛弃cv-qualifiers(const或volatile)。

这是一个简单的例子。首先,您声明两个函数采用指针和引用:

class Bar { ... };
void foo_ptr(Bar*);
void foo_ref(Bar&);

然后你创建一个引用到const:

Bar b;
const Bar& cb = b;

然后你可以使用适当的const_cast调用任一函数:

foo_ptr(const_cast<Bar*>(&cb));
foo_ref(const_cast<Bar&>(cb));

这是我的问题:由于const_cast无法完成其他演员设计的目的,你投射的内容不是很明显吗?换句话说,为什么语言不允许我简单地说:

foo_ptr(const_cast<>(&cb));
foo_ref(const_cast<>(cb));

我只能想到以下两个原因:

a)当我尝试做一些疯狂的事情时,编译器应该阻止我,例如:

foo_ptr(const_cast<int*>(&cb));
foo_ref(const_cast<int&>(cb));

并强迫我明确说明我正在施放的类型然后可以防止行为不端。我发现这个(假设的)解释很弱,因为如果语言支持我写下错误只是为了让编译器纠正我,那就太奇怪了。

b)如果变量既是const又是volatile,则可能存在歧义。在这种情况下,编译器无法告诉我是否试图抛弃其中一个(或两者)。

这是为什么,还是有其他原因?

3 个答案:

答案 0 :(得分:5)

const_cast可用于添加或删除 constvolatile限定符。因此,如果允许这样的语法,则以下所有内容都是const_cast<>(&cb)的合法目标类型:

Bar*                 (1)
const Bar*           (2)
volatile Bar*        (3)
const volatile Bar*  (4)

您打算(1)(2)通常很愚蠢,但可以想象它可能出现在某个地方,也许在某些模板代码中。确实存在问题:(3)(4):您可以删除const资格并添加volatile资格认证

您可以将现有const_cast替换为const_castvolatile_cast两种演员,并禁止案例(2);然后你可以使用其中任何一个没有目标类型。但是,知道转换表达式的类型会更加困难。要知道强制转换表达式是否添加或删除了限定条件,您必须知道源表达式的类型。

没有理由不能使用功能模板来获得你想要的东西:

template <typename T>
T* remove_const(const T* p) {
    return const_cast<T*>(p);
}

您可以轻松地为remove_volatile以及add_constadd_volatile编写类似的函数,这些函数都是隐含的。

答案 1 :(得分:1)

我认为James McNellis已经触及了重要的原因。 const_cast可以添加并删除co​​nstness / volatile。它并不总是很清楚你想要什么。

如果我在const_cast类型的参数上调用const foo,这是否意味着我想将其设为非const,或将volatile添加到其中?或者它应该只是保持 const限定符?如果我在类型(非常量)foo的对象上调用它,它应该添加const吗?或者它应该假设我想删除const-ness,并返回类型(非const)foo的对象?

另一个原因可能只是一致性。

我们有static_cast<T>(x)dynamic_cast<T>(x)reinterpret_cast<T>(x)所以如果const_cast(x)没有类似模板的语法,那就太奇怪了。

答案 2 :(得分:0)

主要原因是使用const_cast可以从

转换
Foo * const * volatile * * 

Foo * * * volatile * const

目的地类型是真的很明显吗?