C++ 提供了五种特定的类型转换:const_cast<>()
、static_cast<>()
、reinterpret_cast<>()
、dynamic_cast<>()
和 C++20 引入的 std::bit_cast<>()
。
请注意,旧的 C 风格类型转换(如 (int)myFloat
)在 C++ 中仍然有效,并在现有代码库中广泛使用。C 风格的类型转换涵盖了所有四种 C++ 类型转换,因此它们更容易出错,因为您试图实现的目的并不总是显而易见的,可能会得到意外的结果。我强烈建议您在新代码中只使用 C++ 风格的类型转换,因为它们更安全,且在代码中更加突出。
模糊基类出现在多个父类共有一个共同的父类时。推荐的解决方案是确保共享的父类自身不具有任何功能。这样,其方法永远不会被调用,从而避免了歧义问题。C++ 还有另一种机制,称为虚拟基类,用于解决您希望共享的父类具有自己功能的情况。
如果共享的父类是一个虚拟基类,则不会有任何歧义。以下代码在 Animal
基类中添加了一个 sleep()
方法,并修改了 Dog
和 Bird
类,使它们作为虚拟基类从 Animal
继承。如果不使用虚拟基类,对 DogBird
对象的 sleep()
调用将是模糊的,并会生成编译器错误,因为 DogBird
将具有两个 Animal
子对象,一个来自 Dog
,一个来自 Bird
。然而,当 Animal
被虚拟继承时,DogBird
只有一个 Animal
类的子对象,因此调用 sleep()
不会有歧义。
class Animal {
public:
virtual void eat() = 0;
virtual void sleep() { cout << "zzzzz...." << endl; }
};
class Dog : public virtual Animal {
public:
virtual void bark() { cout << "Woof!" << endl; }
void eat() override { cout << "The dog ate." << endl; }
};
class Bird : public virtual Animal {
public:
virtual void chirp() { cout << "Chirp!" << endl; }
void eat() override { cout << "The bird ate." << endl; }
};
class DogBird : public Dog, public Bird {
public:
void eat() override { Dog::eat(); }
};
int main() {
DogBird myConfusedAnimal;
myConfusedAnimal.sleep(); // 因为虚拟基类而不模糊
}
注意:虚拟基类是避免类层次结构中歧义的好方法。
C++ 提供了五种特定的类型转换:const_cast<>()
、static_cast<>()
、reinterpret_cast<>()
、dynamic_cast<>()
和 C++20 引入的 std::bit_cast<>()
。第一种在第 1 章中讨论过。第 1 章还介绍了用于某些基本类型之间转换的 static_cast<>()
,但在继承的上下文中还有更多内容。现在您已经熟悉编写自己的类并理解类继承,是时候更仔细地看看这些类型转换了。
请注意,旧的 C 风格类型转换(如 (int)myFloat
)在 C++ 中仍然有效,并在现有代码库中广泛使用。C 风格的类型转换涵盖了所有四种 C++ 类型转换,因此它们更容易出错,因为您试图实现的目的并不总是显而易见的,可能会得到意外的结果。我强烈建议您在新代码中只使用 C++ 风格的类型转换,因为它们更安全,且在代码中更加突出。
static_cast()
static_cast()
用于执行语言直接支持的显式转换。例如,将 int
转换为 double
以避免整数除法:int i { 3 };
int j { 4 };
double result { static_cast<double>(i) / j };
static_cast()
也可用于执行因用户定义的构造函数或转换例程而允许的显式转换。例如,如果类 A 有一个接受 B 对象的构造函数,则可以使用 static_cast()
将 B 对象转换为 A 对象。static_cast()
可用于继承层次结构中的向下转型:class Base { /* ... */ };
class Derived : public Base { /* ... */ };
Base* b { nullptr };
Derived* d { new Derived{} };
b = d; // 向上转型,不需要转换。
d = static_cast<Derived*>(b); // 向下转型,需要转换。
static_cast()
不执行运行时类型检查。可以将任何 Base
指针转换为 Derived
指针,即使 Base
实际上不是 Derived
。static_cast()
不是万能的,它不能将一种类型的指针转换为另一种完全无关的类型的指针,也不能在没有转换构造函数的情况下直接将一种类型的对象转换为另一种类型的对象。reinterpret_cast()
reinterpret_cast()
比 static_cast()
更强大但同时也更不安全。它用于执行 C++ 类型规则技术上不允许的某些转换。void*
。reinterpret_cast()
要格外小心,因为它允许你在不执行任何类型检查的情况下进行转换。reinterpret_cast()
将指针转换为足够大以容纳它的整型类型,反之亦然。但是,尝试将 64 位指针转换为 32 位整数会导致编译错误。std::bit_cast()
std::bit_cast()
是 C++20 中引入的,定义在 <bit>
头文件中。bit_cast()
类似于 reinterpret_cast()
,但它创建一个给定目标类型的新对象,并将源对象的位复制到这个新对象中。它有效地将源对象的位解释为目标对象的位。bit_cast()
要求源对象和目标对象的大小相同且都是平凡可复制的。
float asFloat { 1.23f };
auto asUint { bit_cast<unsigned int>(asFloat) };
if (bit_cast<float>(asUint) == asFloat) {
cout << "Roundtrip success." << endl;
}
bit_cast()
的一个用例是用于平凡可复制类型的二进制 I/O。例如,可以将这些类型的单个字节写入文件,读取文件时,可以使用 bit_cast()
正确解释从文件读取的字节。
平凡可复制类型通常具有以下特征:
dynamic_cast()
dynamic_cast()
在继承层次结构中提供了运行时类型检查。dynamic_cast()
将返回空指针(对于指针版本)或抛出 std::bad_cast
异常(对于引用版本)。Base* b;
Derived* d { new Derived{} };
b = d;
d = dynamic_cast<Derived*>(b);
Base base;
Derived derived;
Base& br { base };
try {
Derived& dr { dynamic_cast<Derived&>(br) };
} catch (const bad_cast&) {
cout << "Bad cast!" << endl;
}
static_cast()
或 reinterpret_cast()
不同,dynamic_cast()
执行运行时(动态)类型检查,而后者即使转换错误也会执行转换。dynamic_cast()
,你的类必须至少有一个虚拟方法。如果类没有虚拟表(vtable),尝试使用 dynamic_cast()
将导致编译错误。情境推荐的转换方法说明移除 const
属性const_cast()
用于移除对象的 const
属性语言直接支持的显式转换static_cast()
例如,从 int
转换到 double
或 bool
用户定义的构造函数或转换支持的显式转换static_cast()
用于用户定义的转换一个类的对象转换为另一个(无关)类的对象bit_cast()
用于无关类之间的对象转换同一继承层次中的类的指针对象转换dynamic_cast()
(推荐) 或 static_cast()
用于继承层次中的指针对象转换同一继承层次中的类的引用对象转换dynamic_cast()
(推荐) 或 static_cast()
用于继承层次中的引用对象转换不相关类型的指针转换reinterpret_cast()
用于完全不相关的指针类型之间的转换不相关类型的引用转换reinterpret_cast()
用于完全不相关的引用类型之间的转换函数指针之间的转换reinterpret_cast()
用于函数指针之间的转换
const_cast()
应谨慎,因为它改变了对象的 const
性质。static_cast()
是最常用的转换类型,适用于许多标准和用户定义的转换。bit_cast()
用于位级别的类型转换,要求源和目标类型大小相同且都是平凡可复制的。dynamic_cast()
在继承层次中提供运行时类型检查,但要求类至少有一个虚拟方法。reinterpret_cast()
提供更广泛的转换能力,但也带来更高的风险,因为它不执行类型检查。本文由哈喽比特于1年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/Yu5Oh6ATxVIZpyW8ddY77A
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。