class="question-status question-originals-of-duplicate">

这个问题已经在这里有了答案:

  • 什么时候应该使用static_cast,dynamic_cast,const_cast和reinterpret_cast? 8个答案

我从事C和C ++代码已有近20年的历史了,但是这些语言的一个方面我从未真正理解过。 我显然使用过常规演员

MyClass *m = (MyClass *)ptr;

各地,但似乎还有其他两种类型的演员,我不知道两者之间的区别。 以下几行代码有什么区别?

MyClass *m = (MyClass *)ptr;
MyClass *m = static_cast<MyClass *>(ptr);
MyClass *m = dynamic_cast<MyClass *>(ptr);

#1楼

避免使用C样式强制转换。

C样式强制转换是const和重新解释强制转换的混合体,很难在代码中查找和替换。 C ++应用程序程序员应避免使用C样式强制转换。


#2楼

static_cast

static_cast用于基本上要撤消隐式转换的情况,但有一些限制和附加条件。 static_cast执行任何运行时检查。 如果您知道引用了特定类型的对象,则应使用此方法,这样就不必进行检查了。 例:

void func(void *data) {// Conversion from MyClass* -> void* is implicitMyClass *c = static_cast<MyClass*>(data);...
}int main() {MyClass c;start_thread(&func, &c)  // func(&c) will be called.join();
}

在此示例中,您知道您传递了MyClass对象,因此不需要任何运行时检查来确保这一点。

dynamic_cast

当您不知道对象的动态类型是什么时, dynamic_cast很有用。 如果所引用的对象不包含强制转换为基类的类型,则它返回一个空指针(当bad_cast转换为引用时,在这种情况下会抛出bad_cast异常)。

if (JumpStm *j = dynamic_cast<JumpStm*>(&stm)) {...
} else if (ExprStm *e = dynamic_cast<ExprStm*>(&stm)) {...
}

如果向下转换(广播到派生类)并且参数类型不是多态的,则不能使用dynamic_cast 。 例如,以下代码无效,因为Base不包含任何虚函数:

struct Base { };
struct Derived : Base { };
int main() {Derived d; Base *b = &d;dynamic_cast<Derived*>(b); // Invalid
}

“向上广播”(广播到基类)对于static_castdynamic_cast始终有效,并且也无需任何static_cast转换,因为“向上广播”是隐式转换。

常规演员

这些转换也称为C样式转换。 C样式强制转换基本上与尝试一系列C ++强制转换序列并获得第一个有效的C ++强制转换相同,而无需考虑dynamic_cast 。 不用说,由于它结合了const_caststatic_castreinterpret_cast所有功能,因此功能更强大,但是它也不安全,因为它不使用dynamic_cast

另外,C样式强制转换不仅允许您执行此操作,而且还允许您安全地强制转换为私有基类,而“等效” static_cast序列将为此提供编译时错误。

由于简洁,有些人喜欢使用C型演员表。 我仅将它们用于数字转换,并在涉及用户定义类型时使用适当的C ++转换,因为它们提供了更严格的检查。


#3楼

静态演员

静态类型转换在兼容类型之间执行转换。 它类似于C样式的强制类型转换,但更具限制性。 例如,C样式强制转换将允许整数指针指向char。

char c = 10;       // 1 byte
int *p = (int*)&c; // 4 bytes

由于这会导致一个4字节的指针指向分配的内存的1字节,因此对该指针进行写入将导致运行时错误或覆盖某些相邻的内存。

*p = 5; // run-time error: stack corruption

与C样式强制转换相反,静态强制转换将允许编译器检查指针和指针数据类型是否兼容,从而允许程序员在编译期间捕获此错误的指针分配。

int *q = static_cast<int*>(&c); // compile-time error

重新诠释演员

为了强制进行指针转换,就像在后台使用C样式强制转换一样,将使用重新解释强制转换。

int *r = reinterpret_cast<int*>(&c); // forced conversion

此强制转换处理某些不相关的类型之间的转换,例如从一种指针类型到另一种不兼容的指针类型。 它将仅执行数据的二进制副本,而不更改基础位模式。 注意,这种低级操作的结果是特定于系统的,因此不可移植。 如果不能完全避免,则应谨慎使用。

动态投放

这个仅用于将对象指针和对象引用转换为继承层次结构中的其他指针或引用类型。 它是通过执行运行时检查来确保指针所指向的对象可以转换为目标类型的完整对象的唯一转换。 为了使运行时检查成为可能,对象必须是多态的。 也就是说,该类必须定义或继承至少一个虚函数。 这是因为编译器只会为此类对象生成所需的运行时类型信息。

动态演员表示例

在下面的示例中,使用动态强制转换将MyChild指针转换为MyBase指针。 由于Child对象包括完整的Base对象,因此这种派生到基本的转换成功。

class MyBase
{ public:virtual void test() {}
};
class MyChild : public MyBase {};int main()
{MyChild *child = new MyChild();MyBase  *base = dynamic_cast<MyBase*>(child); // ok
}

下一个示例尝试将MyBase指针转换为MyChild指针。 由于基础对象不包含完整的子对象,因此该指针转换将失败。 为了表明这一点,动态转换返回一个空指针。 这提供了一种方便的方法来检查运行时转换是否成功。

MyBase  *base = new MyBase();
MyChild *child = dynamic_cast<MyChild*>(base);if (child == 0)
std::cout << "Null pointer returned";

如果转换了引用而不是指针,则动态转换将因抛出bad_cast异常而失败。 这需要使用try-catch语句来处理。

#include <exception>
// …
try
{ MyChild &child = dynamic_cast<MyChild&>(*base);
}
catch(std::bad_cast &e)
{ std::cout << e.what(); // bad dynamic_cast
}

动态或静态投射

使用动态强制转换的优点在于,它允许程序员检查运行时转换是否成功。 缺点是执行此检查会产生性能开销。 出于这个原因,在第一个示例中使用静态转换将是更可取的,因为从派生到基本的转换将永远不会失败。

MyBase *base = static_cast<MyBase*>(child); // ok

但是,在第二个示例中,转换可能成功或失败。 如果MyBase对象包含MyBase实例,它将失败;如果包含MyChild实例,则它将成功。 在某些情况下,可能要等到运行时才能知道。 在这种情况下,动态投射比静态投射更好。

// Succeeds for a MyChild object
MyChild *child = dynamic_cast<MyChild*>(base);

如果从基到源的转换是使用静态转换而不是动态转换执行的,则转换不会失败。 它将返回一个指向不完整对象的指针。 取消引用此类指针可能会导致运行时错误。

// Allowed, but invalid
MyChild *child = static_cast<MyChild*>(base);// Incomplete MyChild object dereferenced
(*child);

const cast

此代码主要用于添加或删除变量的const修饰符。

const int myConst = 5;
int *nonConst = const_cast<int*>(&myConst); // removes const

尽管const cast允许更改常量的值,但这样做仍然是无效代码,可能会导致运行时错误。 例如,如果常量位于只读存储器的一部分中,则可能会发生这种情况。

*nonConst = 10; // potential run-time error

相反,const转换主要在有一个采用非恒定指针参数的函数时使用,即使该函数不会修改指针。

void print(int *p)
{std::cout << *p;
}

然后可以通过使用const强制将函数传递给常量变量。

print(&myConst); // error: cannot convert // const int* to int*print(nonConst); // allowed

来源和更多说明


#4楼

dynamic_cast具有运行时类型检查,并且仅适用于引用和指针,而static_cast不提供运行时类型检查。 有关完整的信息,请参见MSDN文章static_cast Operator


#5楼

您应该查看文章C ++编程/类型转换

它很好地描述了所有不同的演员类型。 以下摘自上述链接:

const_cast

const_cast(expression)const_cast <>()用于添加/删除变量的const(ness)(或volatile-ness)。

static_cast

static_cast(expression)static_cast <>()用于在整数类型之间进行转换。 '例如'char-> long,int-> short等。

静态转换还用于将指针转换为相关类型,例如将void *转换为适当的类型。

dynamic_cast

动态强制转换用于在运行时转换指针和引用,通常目的是在继承链(继承层次结构)的上方或下方强制转换指针或引用。

dynamic_cast(表达式)

目标类型必须是指针或引用类型,并且表达式必须计算为指针或引用。 仅当表达式引用的对象类型与目标类型兼容并且基类具有至少一个虚拟成员函数时,动态转换才起作用。 如果不是,并且正在转换的表达式类型是一个指针,则返回NULL,如果对引用的动态转换失败,则会引发bad_cast异常。 当它没有失败时,动态类型转换将把目标类型的指针或引用返回到表达式所引用的对象。

reinterpret_cast

重新解释类型转换只是将一种类型按位转换为另一种类型。 任何指针或整数类型都可以通过重新解释转换而转换为其他任何类型,很容易导致滥用。 例如,使用重新解释转换,可能会不安全地将整数指针转换为字符串指针。


#6楼

C样式转换将const_cast,static_cast和reinterpret_cast合并在一起。

我希望C ++没有C样式的强制转换。 C ++强制转换正确地突出了(应有的表现;强制转换通常表示做错了事),并正确区分了强制转换执行的不同类型的转换。 它们还允许编写外观相似的函数,例如boost :: lexical_cast,从一致性角度来看,这是相当不错的。


#7楼

仅供参考,我相信Bjarne Stroustrup的话是要避免使用C风格的强制转换,如果可能的话,应该使用static_cast或dynamic_cast。

Barne Stroustrup的C ++风格常见问题解答

采纳您的建议。 我远不是C ++专家。


#8楼

dynamic_cast仅支持指针和引用类型。 如果类型是指针则无法进行NULL则返回NULL如果类型是引用类型则抛出异常。 因此, dynamic_cast可用于检查对象是否为给定类型,而static_cast则不能(给您一个无效值)。

其他答案涵盖了C样式(和其他)强制类型转换。

常规投放vs. static_cast与dynamic_cast [重复]相关推荐

  1. static_cast、dynamic_cast、const_cast和reinterpret_cast总结

    前言 这篇文章总结的是C++中的类型转换,这些小的知识点,有的时候,自己不是很注意,但是在实际开发中确实经常使用的.俗话说的好,不懂自己写的代码的程序员,不是好的程序员:如果一个程序员对于自己写的代码 ...

  2. C/C++ 之 C++强制类型转换(static_cast、dynamic_cast、const_cast、reinterpret_cast)

    文章转载自:https://www.cnblogs.com/chenyangchun/p/6795923.html .在了解这块时,发现了这篇文档,感觉写的很不错! c强制转换与c++强制转换 c 语 ...

  3. 标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast(转载)

    C 风格(C-style)强制转型如下: (T) exdivssion // cast exdivssion to be of type T 函数风格(Function-style)强制转型使用这样的 ...

  4. static_cast、dynamic_cast、reinterpret_cast、const_cast[转]

    C-style cast举例: int i; double d; i = (int) d; 上面的代码就是本来为double类型的d,通过(int)d将其转换成整形值,并将该值赋给整形变量i (注意d ...

  5. static_cast、dynamic_cast、reinterpret_cast、和const_cast

    (转自http://hi.baidu.com/seekvista/blog/item/87845a60ae248845ebf8f8dd.html) 关于强制类型转换的问题,很多书都讨论过,写的最详细的 ...

  6. static_cast与dynamic_cast转换

    static_cast与dynamic_cast转换 C语言中两种类型转换 隐式转换和显式转换 隐式转换:不同数据类型之间赋值和运算,函数调用传递参数,由编译器完成. char ch; int i = ...

  7. C++类型转换运算符 static_cast,dynamic_cast,reinterpret_cast,const_cast

    类型转换是一种让程序猿可以临时或永久性改变编译器对对象的解释机制.可改变对象解释方式的运算符称为类型转换运算符. 为何须要进行类型转换 通常为了实现使用不同环境的个人和厂商编写的模块可以相互调用和协作 ...

  8. 标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast

    C 风格(C-style)强制转型如下: (T) exdivssion // cast exdivssion to be of type T 函数风格(Function-style)强制转型使用这样的 ...

  9. c++ 数据类型转换: static_cast、dynamic_cast、reinterpret_cast和const_cast

    [目录] 引言 static_cast 定义 dynamic_cast 定义 举例:下行转换(把基类的指针或引用转换成子类表示) 举例:上行转换(把子类的指针或引用转换成基类表示) 举例: stati ...

最新文章

  1. java response.write_response设置编码方式 print和write方法的对比
  2. 网络营销——网络营销专员如何加强企业网站推广能力
  3. 数据结构实验之二叉树三:统计叶子数
  4. 【Python教程】 正则表达式 re模块中,反斜杠 “\“分割字符串的正确操作方法
  5. 认识flex中的sprite
  6. SyntaxError: (hbase):100: syntax error, unexpected tIDENTIFIER
  7. stm32f103r6最小系统原理图_超强PCB布线设计经验谈附原理图
  8. 10-排序4 统计工龄 (20 分)
  9. Codeforces 369E Valera and Queries --树状数组+离线操作
  10. 计算机二级c语言编程题库100题下载,计算机二级C语言编程题库100题.doc
  11. 双二阶广义积分器(SOGI)软件锁相(基于双线性变换)推导及实验代码
  12. educoder结构化分析方法-实体-联系图
  13. 硬件蓝牙测试软件,【原创】聊聊蓝牙测试专用硬件工具-Ubertooth
  14. (十二):为什么需要一个新的ORM框架
  15. 如何限制访问一些网站
  16. 未连接到互联网的解决方法(chrome)
  17. Python-Flask实战项目一:仿知乎轻量级web问答平台搭建
  18. zuul+SpringSession的session不一致问题
  19. 快速上手 ClickHouse
  20. 如何在命令行打开mysql

热门文章

  1. ios的延迟执行方法
  2. 3大细节让新站SEO更有竞争优势
  3. C#利用phantomJS抓取AjAX动态页面
  4. hastable与dictionary
  5. Java集合之LinkedHashMap
  6. 今天心情好,一起探讨下《送给大家的200兆SVN代码服务器》怎么管理我们的VS代码?...
  7. Android之ViewPager中包含ViewFlipper时实现双滑动嵌套解决父控件干扰问题
  8. Meego系统的终结 诺基亚QT部门解散
  9. 集群、负载、并发介绍
  10. Linux中 Vi的使用