C++显式转换真的那么糟糕吗?

Lou*_*ong 10 c++ casting

此时我对C++的了解比其他任何事情更具学术性.在我所有的阅读迄今为止,使用显式转换的名为铸件(const_cast,static_cast,reinterpret_cast,dynamic_cast)已经有一个大的警告标签(这很容易明白为什么),这意味着显式转换是对症糟糕的设计,应该只使用在绝望的情况下作为最后的手段.所以,我要问:

使用命名演员的显式转换真的只是陪审团操纵代码还是这个功能有更优雅和积极的应用?后者有一个很好的例子吗?

sha*_*oth 19

有些情况下你不能没有它.喜欢这个.问题在于你有多个继承并且需要将this指针转换为void*同时确保进入的指针void*仍然指向当前对象的右子对象.使用显式强制转换是实现这一目标的唯一方法.

有一种观点认为,如果你不能没有演员阵容你就会有糟糕的设计.我完全不同意这一点 - 不同的情况是可能的,包括上面提到的情况,但也许如果你需要经常使用显式演员,你真的有糟糕的设计.

  • 我同意sharptooth的最终评论,只是因为你有一个明确的演员并不意味着你有不好的代码,但如果你要反复转发其他每一行,那么你需要重新思考一些事情.转换是一种有效的操作,但它不应过度使用. (9认同)

Mat*_* M. 12

在某些情况下,您无法真正避免显式转换.特别是在与C库或设计糟糕的C++库(如COM用于示例的库)之间进行交互时.

一般来说,使用显式演员表是一个红色的鲱鱼.它并不一定意味着代码不好,但确实会引起人们对潜在危险用途的关注.

但是你不应该将4个演员阵容扔在同一个包里:static_castdynamic_cast经常用于向上演员(从Base到Derived)或在相关类型之间导航.它们在代码中的出现是非常正常的(实际上很难在没有代码的情况下编写Visitor模式).

另一方面,使用const_castreinterpret_cast更危险.

  • 通过const_cast尝试修改只读对象是不确定的行为(感谢詹姆斯McNellis修正)
  • reinterpret_cast 通常只用于处理原始内存(分配器)

当然,它们有它们的用途,但在普通代码中不应该遇到它们.为了处理外部或C API,它们可能是必要的.

至少那是我的看法.


Dav*_*ley 6

演员的糟糕程度通常取决于演员的类型.所有这些演员都有合法用途,但有些人比其他演员更难闻.

const_cast用于抛弃constness(因为添加它不需要强制转换).理想情况下,永远不应该使用它.它可以很容易地调用未定义的行为(尝试更改最初指定的对象const),并且无论如何都会破坏const程序的正确性.有时候需要与不const正确的API接口,这可能会例如询问char *他们何时将其视为const char *,但是因为你不应该以这种方式编写API,这表明你正在使用它一个非常古老的API或有人搞砸了.

reinterpret_cast总是依赖于平台,因此在可移植代码中最好是有问题的.此外,除非您对对象的物理结构进行低级操作,否则它不会保留意义.在C和C++中,类型应该是有意义的.一个int是一个数字,这意味着什么; 一个int是基本的串联chars不真正意味着什么.

dynamic_cast通常用于向下转换; 例如from Base *to Derived *,条件是它可以工作或者返回0.这颠覆OO的方式与switch类型标记上的语句大致相同:它移动定义类远离类定义的代码.这将类定义与其他代码耦合在一起,增加了潜在的维护负担.

static_cast用于已知通常正确的数据转换,例如转换和void *转换,类层次结构中已知的安全指针转换,这类事情.关于最坏的情况,你可以说它在某种程度上颠覆了类型系统.当与C库或C标准库的C部分接口时,可能需要它,就像void *在C函数中经常使用的那样.

一般来说,精心设计和编写良好的C++代码将避免上述用例,在某些情况下,因为仅使用强制转换是为了做有潜在危险的事情,而在其他情况下,因为这样的代码往往会避免使用转换.C++类型系统通常被视为维护的好东西,并且强制转换它.