为什么static_cast在逻辑上出于安全目的应拒绝降级或static_cast与安全无关时允许其降级?

时间:2019-03-24 14:39:30

标签: c++

在下面的示例中,编译器接受static_cast下调,导致不确定的行为,而我认为static_cast完全是出于安全考虑(C样式强制转换无法提供)。

#include <iostream>

class Base {
public:
    int x = 10;
};
class Derived1: public Base 
{
public:
    int y = 20;

};
class Derived2 : public Base 
{
public:
    int z = 30;
    int w = 40;

};

int main() {

    Derived1 d1;

    Base* bp1 = static_cast<Base*>(&d1);
    Derived2* dp1 = static_cast<Derived2*>(bp1);

    std::cout << dp1->z << std::endl; // outputs 20
    std::cout << dp1->w << std::endl; // outputs random value
}

3 个答案:

答案 0 :(得分:9)

仅当不确定转换是否成功并且捕获异常或检查nullptr时,才真正使用dynamic_cast。但是,如果您确定 转换将成功,则该语言允许您使用static_cast。如果您错了,那就是您的问题。在理想的世界中,每一个演员都会在100%的时间内成功。但是我们并不生活在理想的世界中。有点像数组下标。 arr[5]的意思是“我绝对确定此数组至少包含6个元素。编译器无需检查”。如果您的阵列比预期的要小,那又是您的问题。

答案 1 :(得分:5)

我真的不知道该怎么说。为什么允许这样的演员?当您需要/想要一个。

不想使用它?别!您可以切换到dynamic_cast(价格更高),也可以不要投放

C ++使您可以做很多需要思考和关心的事情。这就是其中之一。

但是 仍然比C安全。例如,static_cast不允许您将bp1强制转换为UrgleBurgle*

当然,最终您仍然可以根据需要使用C样式的强制类型转换。我的意思是,我不建议这样做,但您可以。 C ++就是关于 choice (通常在一个糟糕的选择和一个稍微不太可怕的选择之间)。

答案 2 :(得分:5)

  

我认为static_cast完全是为了安全(C样式转换无法提供)

static_cast 比C样式转换更安全。但这不是因为不可能出错。这样比较安全,因为它不太可能出错。当我们编写C样式的强制转换时,编译器将通过this list来安抚我们:

  

遇到C样式强制转换表达式时,编译器将尝试   以此顺序将其解释为以下强制转换表达式:

     
      
  1. const_cast<new_type>(expression);
  2.   
  3. static_cast<new_type>(expression),带有扩展名:甚至允许无法访问基类(即,这是指对派生类的指针或引用)也可以强制转换为对明确基类的指针或引用(反之亦然)强制转换会忽略私有继承说明符)。同样适用于将指向成员的指针强制转换为指向明确非虚拟基础的成员的指针;
  4.   
  5. static_cast(带有扩展名),后跟const_cast
  6.   
  7. reinterpret_cast<new_type>(expression);
  8.   
  9. reinterpret_cast,然后是const_cast
  10.   
     

满足各自要求的首选   即使无法编译,也选择了强制转换运算符(请参见   例)。如果演员表可以以多种方式解释为   static_cast后跟const_cast,无法对其进行编译。在   另外,C样式强制转换表示符可以从,至和   指向不完整类类型的指针之间。如果同时表达和   new_type是指向不完整类类型的指针,未指定   是否选择static_castreinterpret_cast

赞成static_cast代替 的要点是,您对最终的演员表有更精细的控制,这确实增加了一定的安全性。但这并没有改变C ++对象模型要求static_cast支持强制转换的事实,即使可能发生未定义的行为也是如此。只有dynamic_cast(顺便说一句不在上面的列表中)对多态类型有更多的安全性,但这并不是没有开销的。