为什么const_cast需要说明你要投射的内容?
根据标准(第5.2.11节),一个const_cast将cv-qualifiers(const或volatile)转换掉。为什么const_cast需要说明你要投射的内容?
下面是一个简单的例子。首先声明两个函数采用指针和参考:使用适当的const_cast
Bar b;
const Bar& cb = b;
,然后你可以调用函数:
class Bar { ... };
void foo_ptr(Bar*);
void foo_ref(Bar&);
然后创建一个参考给const
foo_ptr(const_cast<Bar*>(&cb));
foo_ref(const_cast<Bar&>(cb));
这是我的问题:因为const_cast无法完成其他演员设计的内容,所以您投射的内容不是很明显吗?换句话说,为什么不语让我简单地说:
foo_ptr(const_cast<>(&cb));
foo_ref(const_cast<>(cb));
我能想到的只有以下两个原因:
一)编译器应该停止我,当我尝试做一些发疯一样:
foo_ptr(const_cast<int*>(&cb));
foo_ref(const_cast<int&>(cb));
并迫使我明确指出我铸造它,然后可以让我从行为不端的类型。我觉得这个(假设的)解释很弱,因为如果语言倾向于让我写下错误只是为了让编译器纠正我,那将是很奇怪的。
b)如果变量既是常量又是易失性的,则可能存在歧义。在这种情况下,编译器将无法告诉我是否试图抛弃这一个或另一个(或两者)。
这是为什么,还是有其他原因?
const_cast
可用于添加或删除const
和volatile
限定符。所以,如果这样的语法被允许,以下所有的将是const_cast<>(&cb)
合法目标类型:
Bar* (1)
const Bar* (2)
volatile Bar* (3)
const volatile Bar* (4)
您打算(1)。 (2)通常很愚蠢,但可以想象,它可能发生在某处,也许在某些模板代码中。 (3)和(4)的确存在以下问题:您可以删除const
资格,并将所有资格都添加到单个演员表中。
你可以用一对石膏,const_cast
volatile_cast
和的取代现有const_cast
,和禁止的情况下(2);那么你可以使用它们中的任何一个而不使用目标类型。然而,知道演员表达的类型则更加困难。要知道演员表达式是否添加或删除限定条件,您必须知道源表达式的类型。
没有理由你不能使用函数模板来获得你想要的东西:
template <typename T>
T* remove_const(const T* p) {
return const_cast<T*>(p);
}
你可以很容易地编写remove_volatile
和add_const
和add_volatile
类似的功能,这两者都是隐含的。
我认为詹姆斯麦克奈利斯已经谈到了重要的原因。 const_cast
都可以加并删除常量/不稳定性。这并不总是清楚你想要什么。
如果我打电话const_cast
上const foo
类型的参数,这是否意味着我想让它不const
,或添加volatile
呢?或者它应该只是保留const
限定符?如果我在类型(非const)foo
的对象上调用它,它应该添加const吗?还是应该假设我想删除常量,并返回一个类型为(非常量)foo
的对象呢?
另一个原因可能只是一致性。
我们有static_cast<T>(x)
,dynamic_cast<T>(x)
,reinterpret_cast<T>(x)
所以如果没有类似于模板的语法就有const_cast(x)
,看起来很奇怪。
的主要原因是使用const_cast
你可以从
Foo * const * volatile * *
转换为
Foo * * * volatile * const
是否真的明显的目标类型是什么?
当然,该运算符还允许`const_cast (&b)`(其中b不是`const')和相同的结果类型集合,所以即使它没有处理波动性,您也必须问Alexandros无论const_cast 是否应该切换常量或默认添加或删除它(后者会使它有点用词不当)。正如你所说,在模板中,通常需要在不知道开始的情况下获得const或非const类型。 – 2010-12-08 03:07:21
@Tony:关于b不需要是const的好处。更一般地说,尽管我知道const_cast也可以添加const,但我的隐含假设是没有人这样做(因为还有其他方法可以这样做),因此如果输入b不是const,那么就让它成为。 – 2010-12-08 03:22:35