2016-12-31 52 views
2

如果您将旧的C风格的类型转换为类型A到类型B,而类型A不能转换为类型B,那么C++标准是否定义了特定的行为?反之亦然?是否定义了运行时错误的C风格转换的行为?

会有一个已知的可见行为,可以被认为是在运行时使用此非法转换的症状吗?

+0

我认为你应该提供一个例子。例如:你在谈论POD类型,类别,原始类型,指针,...? – UnholySheep

+1

好吧,全部都是 – Allahjane

+1

取决于实际的代码,C风格的转换可以等同于3种不同C++类型转换('static_cast','reinterpret_cast'或'const_cast')中的任何一种。这些'static_cast'会抛出编译时错误,而'reinterpret_cast'会(在大多数情况下)导致UB(如果抛出是非法的) – UnholySheep

回答

4

四种C++风格演员中只有一种决定了演员在演出时的合法性,即dynamic_cast

C风格演员阵容对应于其他三个阵容的组合(static_cast,reinterpret_cast,const_cast)。这些演员的有效性是在编译时确定的,或者如果在编译时无法确定,那么演员被认为是有效的。 C风格演员绝不会像dynamic_cast那样行事。

因此,在运行时“失败”的C风格转换,即打破了有效性假设,导致未定义的行为。所以:

如果您将旧的C风格的类型转换为类型A到类型B,其中类型A不能转换为类型B,反之亦然,C++标准是否定义了特定的行为?

会不会有,可以认为是使用这种在运行时非法投症状已知可见的行为?

+0

感谢这就是我想知道的全部 – Allahjane

+0

[另请参见此处](http://stackoverflow.com/questions/17925124/can-i-cast-a-derived-class-to-a-private-base-class-using -c-style-cast),这个C风格转换不等同于C++风格转换的任何组合 –

0

编译器会赶上他们中的一些,但不是全部。这是一个灾难性的铸件的例子:

#include <iostream> 
#include <string> 

using namespace std; 

class A { 
public: 
     A(std::string s, int x) : m_s(s), m_x(x) {} 

     void print() { cout << "A::print(): str = " << m_s << ", x = " << m_x << endl; } 

private: 
     std::string m_s; 
     int m_x; 
}; 

class B { 
public: 
     B(int x) : m_x(x) {} 
     void print() { m_x++; cout << "B::print(): x = " << m_x << endl; } 

private: 
     int m_x; 

}; 

int main(int argc, char **argv) { 

     A *a = new A("abc", 1); 
     a->print(); 
     B *b = (B*)a; 
     b->print(); 

     a->print(); 

     return 0; 
} 

海合会结果(Ubuntu的5.4.0-6ubuntu1〜16.04.4)5.4.0 20160609:

A::print(): str = abc, x = 1 
B::print(): x = 24828977 
A::print(): str = bc, x = 1 

是的,我们叫B的方法上A的数据,这意味着我们的C风格演员工作为reinterpret_castreinterpret_cast只需要一个内存区域,并允许你对待是不同的东西。这里没有安全带。

在另一方面,如果你尝试编译这样的事情

A a; 
    B b; 
    a = (A)b; 
    return 0; 

会造成static_cast和编译时错误。所以C风格的转换结果取决于上下文。

这是NIGHTMARE当处理模板和auto

为了避免此问题,使用static_cast(用于编译时检查)和dynamic_cast(运行时检查)或reinterpret_cast(用于指针和POD),写明你的意图。

+0

实际上你的结果可能只发生在你的机器/编译器上 - 我得到一个[运行时错误](http:// ideone的.com/CsdaXh)。 b:print();'调用*未定义的行为* – UnholySheep

+0

B :: print()修改由'std :: string'占据的sizeof(int)'字节。你可能会在那里观察到内存腐败 – ezaquarii

+0

[reinterpret_cast']的文档(http://en.cppreference.com/w/cpp/language/reinterpret_cast)在此清楚 - 你正在调用UB。也不知道内存损坏是如何影响的,因为您的结果不能保证,并且不同的编译器会引发运行时错误。 – UnholySheep

相关问题