Ymi*_*mir 65 c++ refactoring casting
我在15K LOC C++项目中使用C风格的强制转换,90%的时间用于子类和基类之间的强制转换.
即使我读到使用它们是不好的,并且它们可能导致严重的错误,因为它们不像C++演员那样安全,我仍然觉得使用它们非常精细和舒适.
到目前为止,我没有遇到过我的项目中的一个错误,例如,一个意外错误的C-Style演员 - 真的.
我没有使用它们有两个主要原因:
我的问题:
我使用C++为我提供的所有其他优点,包括虚拟和抽象基类,命名空间,STL等,而不是新的类型转换语法." 你为什么不只是使用C呢? " 这个论点对我来说不起作用.
tem*_*def 89
正如您所提到的,C++风格的演员表的主要优点是类型安全.C++中的每个演员都处理一种特定类型的转换(或一系列相关转换),因此编译器可以检查您是否意外地进行了您想要的更多转换,或者从根本上不安全的一系列转换.
要考虑的一件事是,尽管你觉得使用C风格的演员阵容很舒服,虽然很高兴你没有犯过任何错误,但是其他在代码库上工作的人可能不会那么轻易使用这些演员阵容.就像你一样.使用强制转换操作符可以使代码更加自我记录.如果你在某处有C风格的演员,那么阅读代码的其他人可能无法立即推断出你正在做什么.如果他们看到类似的东西
T* ptr = (T*) var;
Run Code Online (Sandbox Code Playgroud)
他们可能无法立即判断出这是不是
const岬关闭的var虽然他们可以从上下文中收集到这一点,但是如果你使用类似的演员,会发生什么事情会更加明显
T* ptr = static_cast<T*>(var);
Run Code Online (Sandbox Code Playgroud)
要么
T* ptr = const_cast<T*>(var);
Run Code Online (Sandbox Code Playgroud)
更喜欢C++风格的转换操作符的另一个原因是它们使代码更易于修改.例如,假设我有这个功能:
void DoSomething(Base* ptr) {
Derived* derived = (Derived *) ptr;
DoSomethingElse(derived);
}
Run Code Online (Sandbox Code Playgroud)
现在,假设我意识到这个函数不应该对其参数进行任何更改,所以我决定标记它const.例如:
void DoSomething(const Base* ptr) {
Derived* derived = (Derived *) ptr;
DoSomethingElse(derived);
}
Run Code Online (Sandbox Code Playgroud)
但是现在我们遇到了一个问题 - 我的C风格的演员阵容过去只是做了一个向下的人,现在也脱掉了const.这可能导致一个容易DoSomethingElse出错的错误,即改变我传入的指针,即使该DoSomething方法本身承诺不这样做.如果我把这段代码写成了
void DoSomething(Base* ptr) {
Derived* derived = static_cast<Derived *>(ptr);
DoSomethingElse(derived);
}
Run Code Online (Sandbox Code Playgroud)
然后添加const以下内容来更改代码:
void DoSomething(const Base* ptr) {
Derived* derived = static_cast<Derived *>(ptr);
DoSomethingElse(derived);
}
Run Code Online (Sandbox Code Playgroud)
现在我会收到一个编译器错误,告诉我我的旧版本已经损坏,这可能会让我发现代码中存在逻辑错误(即,它会DoSomethingElse改变它的参数,所以我不能天真地制作ptr一个指针 -到 - const.
简而言之,使用C++强制转换运算符可以使代码更具可读性和可维护性.它使代码背后的逻辑更加明确.并且通过让编译器在您创建错误时或稍后在返回并更改旧代码时捕获错误,可以减少错误.由于这些主要原因,我建议将来尝试使用C++风格的转换操作符.
至于你是否应该回去尝试用C++风格的演员阵容替换你当前的C风格演员阵容,这真的取决于你.作为一个练习,我建议你只是练习学习你正在使用的演员阵容.另外,你可能会发现一个逻辑错误,这将使你的搜索值得一试!
sbi*_*sbi 33
在我曾经工作的公司中,我们曾经不得不将数百万行代码应用程序移植到新平台上.最初只是"只是另一个Unix平台的另一个端口"(代码已经运行在Windows,OSX和六个类Unix平台上),结果是一个巨大的问题.IIRC,原因是该平台具有相当严格的对齐要求,并且我们的一些演员因未对准而绊倒硬件异常.
如果不是因为这些演员阵容的某些百分比是C风格的演员阵容,这本来很容易解决.这些都不可能有效地进行.搜索出现了数以万计的代码行,这些代码都必须由人工手动检查,其中99.99%完全不相关.
我们人类倾向于错过这些难以发现的一些演员阵容,这无疑会有所帮助,然后必须在另一轮审查数万行代码中找到它们,其中99.99%与完全相同.第一轮.
这项任务几乎不可能在给定的时间内完成,并且几乎打破了公司的支持,因为如果我们在截止日期前滑倒,他们将面临严厉的合同处罚.
毋庸置疑,之后决定用他们的C++对手替换所有C风格的演员阵容.但是,如果我们必须制作该端口之前存在此政策......
Edw*_*nge 10
(为什么)我应该重构我的项目以使用C++风格的演员表吗?
是.出于同样的原因,您将来应该使用它们.
为什么我应该在未来的项目中使用C++风格的演员表?
这份名单实际上相当长,但我会过去最重要的.
首先,他们清楚地说明演员的意图.阅读"static_cast"你知道作者打算执行静态转换,而不是重新解释或const.
其次,他们只做一件事,而且只做一件事.例如,你不能意外抛弃constness.
他们很容易搜索.搜索"const_cast"以查找到const的所有强制转换.你会如何用C风格做到这一点?你做不到.
当本地代码语义改变时,它们不会改变强制类型.例如,(Widget*)(blah)如果Widget停止从指向其的任何类型继承继承,将默默地更改为重新解释.如果Widget定义不在本地可用,它也会更改为重新解释转换.如果你使用新式的强制转换,你将得到编译器呕吐而不是对语句的无声重新解释.
你可以进行动态演员表演.C风格的演员阵容无法做到这一点.
那么两部分:
(为什么)我应该重构我的项目以使用C++风格的演员表吗?
如果您的代码有效.然后不要修复它.保持原状.无论如何,找到C演员阵容可能会相当困难.如果您正在处理代码并遇到C强制转换,请根据需要进行更改.
为什么我应该在未来的项目中使用C++风格的演员表?
因为C演员很容易出错.