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

Ale*_*lis 4 c++ standards casting

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

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

class Bar { ... };
void foo_ptr(Bar*);
void foo_ref(Bar&);
Run Code Online (Sandbox Code Playgroud)

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

Bar b;
const Bar& cb = b;
Run Code Online (Sandbox Code Playgroud)

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

foo_ptr(const_cast<Bar*>(&cb));
foo_ref(const_cast<Bar&>(cb));
Run Code Online (Sandbox Code Playgroud)

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

foo_ptr(const_cast<>(&cb));
foo_ref(const_cast<>(cb));
Run Code Online (Sandbox Code Playgroud)

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

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

foo_ptr(const_cast<int*>(&cb));
foo_ref(const_cast<int&>(cb));
Run Code Online (Sandbox Code Playgroud)

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

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

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

Jam*_*lis 5

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

Bar*                 (1)
const Bar*           (2)
volatile Bar*        (3)
const volatile Bar*  (4)
Run Code Online (Sandbox Code Playgroud)

你打算(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);
}
Run Code Online (Sandbox Code Playgroud)

你可以很容易地编写类似的功能remove_volatileadd_constadd_volatile,这两者都是隐含的.

  • 我们甚至都没有谈过多级指针:) (2认同)