C++;类型转换:使用显式转换的好处? 使用这些运算符代替C++中的隐式转换有什么好处?
C++;类型转换:使用显式转换的好处? 使用这些运算符代替C++中的隐式转换有什么好处?,c++,casting,C++,Casting,dynamic_cast <new_type> (expression) reinterpret_cast <new_type> (expression) static_cast <new_type> (expression) dynamic\u cast(表达式) 重新解释演员阵容(表达) 静态转换(表达式) 为什么,在哪里,在什么情况下我们应该使用它们?它们真的很少在OOP中使用吗?就像所有其他隐式转换一样,它可能隐藏了开发人员/审阅者没有想到的逻辑
dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
dynamic\u cast(表达式)
重新解释演员阵容(表达)
静态转换(表达式)
为什么,在哪里,在什么情况下我们应该使用它们?它们真的很少在OOP中使用吗?就像所有其他隐式转换一样,它可能隐藏了开发人员/审阅者没有想到的逻辑,掩盖了错误。从您提供的转换列表中,用于支持隐式转换的唯一有意义的是静态转换 dynamic_cast用于将超类向下转换为其子类。这不能隐式发生,实际上在OOP中并不罕见。静态强制转换也可以用于此类强制转换,但它更危险,因为它在运行时不会检查向下强制转换是否有效
最后一个演员,reinterpret_cast,应该非常小心地使用,因为它是所有演员中最危险的。基本上,你可以用它将任何东西转换成任何东西,但作为程序员,你必须确保这种转换在语义上是有意义的,因为你基本上通过执行这种转换来关闭类型检查。一般来说,我看到这些类型的转换出现在代码中,当一些东西不再构建时,可能是因为我们已经开始使用一个新的编译器,它对隐式转换更严格,所以这就是隐式转换的关键“好处”。显然,在这种情况下正确的做法是以其他方式更改代码 动态_cast可用于铸造具有多态性的“上游”。所以如果你有这样一个结构 基础->派生A 基础->派生B 你可以做动态演员(b);(b是指向基的指针,但实际上是派生的_b) 如果它不是派生类,则返回的将是0,而不是转换后的指针 这比静态转换慢得多,因为检查是在运行时而不是编译时完成的,但预期用途不同 reinterpret_cast只是更改了类型标签,启用了时髦的C风格的FX(或者通常称为“类型双关”),这对协议/低级工作很有用,但应该谨慎使用
通常,代码中的大量强制转换表示您的代码设计有问题。只想添加一个使用reinterpret_cast的示例。假设一个库给你一个指向原始网络数据包的指针。要理解数据结构,可以使用结构,然后将指针强制转换到这些结构。请注意,编译器无法验证您是在做一些合理的事情,还是只是在内存中读取不应该读取的内容。在现实生活中,您应该首先检查数据包的大小,以确定它足够大,可以容纳您的结构 在下面的代码中,IPfragment构造函数获取一个数据包,然后将该指针强制转换为合理的内容。我添加了以下定义 如果有人仍然认为使用reinterpret_cast是不合理的,我很高兴在这里讨论一种更好的方法
IPfragment::IPfragment( const byte* const pkt_data ) :
ethernetHeader( reinterpret_cast< const EthernetHeader* >( pkt_data ) )
, ipHeader ( reinterpret_cast< const IPheader* >( pkt_data + ETHER_HEADER_LEN ) )
, payload ( reinterpret_cast< const byte* >( ipHeader )
+ ( ipHeader->ver_hl & 0x0f ) *4 )
{
}
<>使用C++的转换而不是C样式的转换的好处之一是它们很容易搜索。他们还分离出C型铸型的不同应用,使气味易于识别 例如,reinterpret_cast的grep可以很容易地发现许多潜在问题和糟糕的设计,而正确识别C样式转换的正则表达式需要进一步检查以识别糟糕的转换
如果需要强制转换,我将总是使用C++的转换和从不使用C样式的转换。p>
参见C++编码标准,萨特和Alexandrescu,第95项。
< P>一个非常简短的答案,这些转换的好处是它们执行特定的函数,使代码具有描述性。C风格的演员阵容是全能的,可以让你摆脱各种各样的错误。那些习惯使用C的人可能会抱怨说,这些演员阵容很难写出。这实际上被其他人认为是一件好事:它阻止程序员在他们的代码上散布强制类型转换,这是问题代码的一个非常明显的迹象。最后,通过文本搜索很容易找到它们。Duplicates。typedef uint8_t byte ;
typedef uint16_t word ;
typedef uint32_t dword ;
#define ETHER_ADDR_LEN 6 // Ethernet addresses are 6 bytes
#define ETHER_HEADER_LEN 14 // Ethernet headers are 14 bytes
#define ETHER_TYPE_IP4 8
struct EthernetHeader
{
byte etherDestHost[ETHER_ADDR_LEN]; // Destination host address
byte etherSrcHost [ETHER_ADDR_LEN]; // Source host address
word etherType; // IP? ARP? RARP? etc
};
/* 4 bytes IP address */
struct IPaddress
{
byte byte1, byte2, byte3, byte4;
};
/* IPv4 header */
struct IPheader
{
byte ver_hl ; // Version (4 bits) + Internet header length (4 bits)
byte tos ; // Type of service
word tlen ; // Total length
word identification ; // Identification
word flags_fo ; // Flags (3 bits) + Fragment offset (13 bits)
byte ttl ; // Time to live
byte proto ; // Protocol
word crc ; // Header checksum
IPaddress saddr ; // Source address
IPaddress daddr ; // Destination address
dword op_pad ; // Option + Padding
};
class IPfragment
{
public:
const IPheader* const ipHeader;
const EthernetHeader* const ethernetHeader;
const byte* const payload;
IPfragment( const byte* const pkt_data );
// rest of code omitted for brevity
}