根据标准(§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,则可能存在歧义。在这种情况下,编译器无法告诉我是否试图抛弃其中一个(或两者)。
这是为什么,还是有其他原因?
答案 0 :(得分:5)
const_cast
可用于添加或删除 const
和volatile
限定符。因此,如果允许这样的语法,则以下所有内容都是const_cast<>(&cb)
的合法目标类型:
Bar* (1)
const Bar* (2)
volatile Bar* (3)
const volatile Bar* (4)
您打算(1)。 (2)通常很愚蠢,但可以想象它可能出现在某个地方,也许在某些模板代码中。确实存在问题:(3)和(4):您可以删除const
资格并添加volatile
资格认证
您可以将现有const_cast
替换为const_cast
和volatile_cast
两种演员,并禁止案例(2);然后你可以使用其中任何一个没有目标类型。但是,知道转换表达式的类型会更加困难。要知道强制转换表达式是否添加或删除了限定条件,您必须知道源表达式的类型。
没有理由不能使用功能模板来获得你想要的东西:
template <typename T>
T* remove_const(const T* p) {
return const_cast<T*>(p);
}
您可以轻松地为remove_volatile
以及add_const
和add_volatile
编写类似的函数,这些函数都是隐含的。
答案 1 :(得分:1)
我认为James McNellis已经触及了重要的原因。 const_cast
可以添加并删除constness / 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
目的地类型是真的很明显吗?