常规演员阵容与静态演员阵容与动态演员阵容 我已经写了C和C++代码将近二十年了,但是这些语言的一个方面我从来没有真正理解。我显然用过常规的石膏,比如 MyClass *m = (MyClass *)ptr;

常规演员阵容与静态演员阵容与动态演员阵容 我已经写了C和C++代码将近二十年了,但是这些语言的一个方面我从来没有真正理解。我显然用过常规的石膏,比如 MyClass *m = (MyClass *)ptr;,c++,pointers,casting,C++,Pointers,Casting,到处都是,但似乎还有另外两种类型的演员,我不知道有什么区别。以下代码行之间有什么区别 MyClass *m = (MyClass *)ptr; MyClass *m = static_cast<MyClass *>(ptr); MyClass *m = dynamic_cast<MyClass *>(ptr); MyClass*m=(MyClass*)ptr; MyClass*m=静态投影(ptr); MyClass*m=动态投影(ptr); dynamic\u cas

到处都是,但似乎还有另外两种类型的演员,我不知道有什么区别。以下代码行之间有什么区别

MyClass *m = (MyClass *)ptr;
MyClass *m = static_cast<MyClass *>(ptr);
MyClass *m = dynamic_cast<MyClass *>(ptr);
MyClass*m=(MyClass*)ptr;
MyClass*m=静态投影(ptr);
MyClass*m=动态投影(ptr);

dynamic\u cast
具有运行时类型检查功能,并且仅适用于引用和指针,而
static\u cast
不提供运行时类型检查功能。有关完整信息,请参阅MSDN文章。

您应该看看这篇文章

它包含对所有不同类型强制转换的良好描述。以下内容摘自上述链接:

康斯塔

const_cast(表达式)const_cast()用于添加/删除 变量的常数(或易变性)

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

static_cast(表达式)static_cast()用于在 整数类型。”e、 字符->长,整数->短等

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

动态浇铸

动态强制转换用于在运行时转换指针和引用, 通常用于向上或向下投射指针或引用 继承链(继承层次结构)

动态_cast(表达式)

目标类型必须是指针或引用类型,并且 表达式的计算结果必须是指针或引用。动态铸造工程 仅当表达式引用的对象类型为 与目标类型兼容,并且基类至少有一个 虚拟成员函数。如果不是,以及要强制转换的表达式的类型 是指针,如果对引用进行动态强制转换,则返回NULL 如果失败,将引发错误的\u强制转换异常。当它没有失败时,动态 cast返回指向对象的目标类型的指针或引用 这个表达所指的

重新解释

Reinterpret强制转换只是将一种类型按位强制转换为另一种类型。任何指针 或者,可以使用reinterpret cast将整型铸造到任何其他类型, 容易被误用。例如,使用reinterpret cast one 可能不安全地将整数指针强制转换为字符串指针


C样式转换将常量转换、静态转换和重新解释转换合并


我希望C++没有C样式的转换。C++正确地(如它们应该的那样)突出显示;铸件通常表示做不好的事情,并正确地区分铸件执行的不同类型的转换。它们还允许编写类似的函数,例如boost::lexical_cast,从一致性的角度来看,这非常好。

仅供参考,我相信Bjarne Stroustrup曾说过,要避免使用C风格的强制转换,如果可能的话,应该使用静态强制转换或动态强制转换


不管你想做什么,都要接受这个建议。我远不是C++大师。

< P>避免使用C风格的铸件。< /P> C样式转换是const和reinterpret转换的混合,在代码中很难找到和替换。C++应用程序程序员应避免C风格的转换。
static_cast
用于基本上想要反转隐式转换的情况,但有一些限制和添加<代码>静态_cast不执行运行时检查。如果您知道您引用的是特定类型的对象,那么应该使用此选项,因此不需要进行检查。例如:

void func(void *data) {
  // Conversion from MyClass* -> void* is implicit
  MyClass *c = static_cast<MyClass*>(data);
  ...
}

int main() {
  MyClass c;
  start_thread(&func, &c)  // func(&c) will be called
      .join();
}
如果向下转换(转换到派生类)并且参数类型不是多态的,则不能使用
dynamic\u cast
。例如,以下代码无效,因为
Base
不包含任何虚拟函数:

struct Base { };
struct Derived : Base { };
int main() {
  Derived d; Base *b = &d;
  dynamic_cast<Derived*>(b); // Invalid
}
struct Base{};
派生结构:基{};
int main(){
派生d;基*b=&d;
动态_cast(b);//无效
}
“向上转换”(转换到基类)在
静态转换
动态转换
时始终有效,也没有任何转换,因为“向上转换”是一种隐式转换

普通演员 这些类型转换也称为C样式转换。C样式的CAST基本上与尝试一系列C++的Casts相一致,并且采用第一个C++的Cask,而不考虑<代码> DyrimCysCAP。不用说,它结合了所有的
const\u cast
static\u cast
reinterpret\u cast
,因此功能更强大,但它也不安全,因为它不使用
dynamic\u cast

此外,C风格的强制转换不仅允许您这样做,而且还允许您安全地强制转换到私有基类,而“等效的”
static\u cast
序列将为此给您一个编译时错误


有些人喜欢C风格的演员,因为他们的简短。我只使用它们进行数值转换,当涉及到用户定义类型时,使用适当的C++转换,因为它们提供了更严格的检查。

< P> <代码> DyrimCysCase>代码>只支持指针和引用类型。如果类型是指针,则无法强制转换;如果类型是引用类型,则抛出异常,则返回
NULL
。因此,
dynamic_-cast
可以用来检查对象是否属于给定类型,
static_-cast
不能(您只会得到一个无效值)

其他答案中已涵盖C型(和其他)类型

静态浇铸 静态强制转换在兼容类型之间执行转换。它类似于C样式转换,但限制性更强。例如,C样式转换允许整数指针指向字符。
char c = 10;       // 1 byte
int *p = (int*)&c; // 4 bytes
由于这将导致一个4字节指针指向分配内存的1字节,因此写入该指针将导致运行时e
*p = 5; // run-time error: stack corruption
int *q = static_cast<int*>(&c); // compile-time error
int *r = reinterpret_cast<int*>(&c); // forced conversion
class MyBase 
{ 
  public:
  virtual void test() {}
};
class MyChild : public MyBase {};



int main()
{
  MyChild *child = new MyChild();
  MyBase  *base = dynamic_cast<MyBase*>(child); // ok
}
MyBase  *base = new MyBase();
MyChild *child = dynamic_cast<MyChild*>(base);

 
if (child == 0) 
std::cout << "Null pointer returned";
#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
// 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 int myConst = 5;
int *nonConst = const_cast<int*>(&myConst); // removes const
*nonConst = 10; // potential run-time error
void print(int *p) 
{
   std::cout << *p;
}
print(&myConst); // error: cannot convert 
                 // const int* to int*
 
print(nonConst); // allowed