×

dynamic_cast 数据类型

dynamic_cast(C++中的数据类型强制转换)

admin admin 发表于2023-03-23 01:32:30 浏览70 评论0

抢沙发发表评论

本文目录

C++中的数据类型强制转换

C  风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是:

TYPE b = (TYPE)a

C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用。

const_cast,字面上理解就是去const属性。

static_cast,命名上理解是静态类型转换。如int转换成char。

dynamic_cast,命名上理解是动态类型转换。如子类和父类之间的多态类型转换。

reinterpreter_cast,仅仅重新解释类型,但没有进行二进制的转换。

4种类型转换的格式,如:

TYPE B = static_cast(TYPE)(a)

const_cast

去掉类型的const或volatile属性。

struct SA {

int i;

};

const SA ra;

//ra.i = 10; //直接修改const类型,编译错误

SA &rb = const_castSA&》(ra);

rb.i = 10;

static_cast

类似于C风格的强制转换。无条件转换,静态类型转换。用于:

1. 基类和子类之间转换:其中子类指针转换成父类指针是安全的;但父类指针转换成子类指针是不安全的。(基类和子类之间的动态类型转换建议用dynamic_cast)

2. 基本数据类型转换。enum, struct, int, char, float等。static_cast不能进行无关类型(如非基类和子类)指针之间的转换。

3. 把空指针转换成目标类型的空指针。

4. 把任何类型的表达式转换成void类型。

5. static_cast不能去掉类型的const、volitale属性(用const_cast)。

int n = 6;

double d = static_castdouble》(n); // 基本类型转换

int *pn = &n;

double *d = static_castdouble *》(&n) //无关类型指针转换,编译错误

void *p = static_castvoid *》(pn); //任意类型转换成void类型

dynamic_cast

有条件转换,动态类型转换,运行时类型安全检查(转换失败返回NULL):

1. 安全的基类和子类之间转换。

2. 必须要有虚函数。

3. 相同基类不同子类之间的交叉转换。但结果是NULL。

class BaseClass {

public:

int m_iNum;

virtual void foo(){};

//基类必须有虚函数。保持多台特性才能使用dynamic_cast

};

class DerivedClass: public BaseClass {

public:

char *m_szName;

void bar(){};

};

BaseClass* pb = new DerivedClass();

DerivedClass *pd1 = static_castDerivedClass *》(pb);

//子类-》父类,静态类型转换,正确但不推荐

DerivedClass *pd2 = dynamic_castDerivedClass *》(pb);

//子类-》父类,动态类型转换,正确

BaseClass* pb2 = new BaseClass();

DerivedClass *pd21 = static_castDerivedClass *》(pb2);

//父类-》子类,静态类型转换,危险!访问子类m_szName成员越界

DerivedClass *pd22 = dynamic_castDerivedClass *》(pb2);

//父类-》子类,动态类型转换,安全的。结果是NULL

reinterpreter_cast

仅仅重新解释类型,但没有进行二进制的转换:

1. 转换的类型必须是一个指针、引用、算术类型、函数指针或者成员指针。

2. 在比特位级别上进行转换。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。但不能将非32bit的实例转成指针。

3. 最普通的用途就是在函数指针类型之间进行转换。

4. 很难保证移植性。

int doSomething(){return 0;};

typedef void(*FuncPtr)();

//FuncPtr is 一个指向函数的指针,该函数没有参数,返回值类型为 void

FuncPtr funcPtrArray;

//10个FuncPtrs指针的数组 让我们假设你希望(因为某些莫名其妙的原因)把一个指向下面函数的指针存入funcPtrArray数组:

funcPtrArray = &doSomething;

// 编译错误!类型不匹配,reinterpret_cast可以让编译器以你的方法去看待它们:funcPtrArray

funcPtrArray = reinterpret_castFuncPtr》(&doSomething);

//不同函数指针类型之间进行转换

总 结

去const属性用const_cast。

基本类型转换用static_cast。

多态类之间的类型转换用daynamic_cast。

不同类型的指针类型转换用reinterpreter_cast。

c++中的关键字const_cast,dynamic_cast,reinterpret_cast,static_cast都是些什么东西啊


强制类型转换运算符:C++有四种强制类型转换符,分别是dynamic_cast,const_cast,static_cast,reinterpret_cast。其中dynamic_cast与运行时类型转换密切相关,在这里我们先介绍dynamic_cast,其他三种在后面介绍。
6.1、dynamic_cast强制转换运算符:该转换符用于将一个指向派生类的基类指针或引用转换为派生类的指针或引用,注意dynamic_cast转换符只能用于含有虚函数的类,其表达式为dynamic_cast《类型》(表达式),其中的类型是指把表达式要转换成的目标类型,比如含有虚函数的基类B和从基类B派生出的派生类D,则B *pb; D *pd, md; pb=&md pd=dynamic《D*》(pb); 最后一条语句表示把指向派生类D的基类指针pb转换为派生类D的指针,然后将这个指针赋给派生类D的指针pd,有人可能会觉得这样做没有意义,既然指针pd要指向派生类为什么不pd=&md这样做更直接呢?有些时候我们需要强制转换,比如如果指向派生类的基类指针B想访问派生类D中的除虚函数之外的成员时就需要把该指针转换为指向派生类D的指针,以达到访问派生类D中特有的成员的目的,比如派生类D中含有特有的成员函数g(),这时可以这样来访问该成员dynamic_cast《D*》(pb)-》g();因为dynamic_cast转换后的结果是一个指向派生类的指针,所以可以这样访问派生类中特有的成员。但是该语句不影响原来的指针的类型,即基类指针pb仍然是指向基类B的。如果单独使用该指针仍然不能访问派生类中特有的成员。一般情况下不推见这样使用dynamic_cast转换符,因为dynamic_cast的转换并不会总是成功的,具体情况在后面介绍。
6.2、dynamic_cast的注意事项:dynamic_cast转换符只能用于指针或者引用。dynamic_cast转换符只能用于含有虚函数的类。dynamic_cast转换操作符在执行类型转换时首先将检查能否成功转换,如果能成功转换则转换之,如果转换失败,如果是指针则反回一个0值,如果是转换的是引用,则抛出一个bad_cast异常,所以在使用dynamic_cast转换之间应使用if语句对其转换成功与否进行测试,比如pd=dynamic_cast《D*》(pb); if(pd){…}else{…},或者这样测试if(dynamic_cast《D*》(pb)){…}else{…}。
6.3、const_cast操作符:其表达式为const_cast《类型》(表达式),其中类型指要把表达式转换为的目标类型。该操作符用于改变const和volatile,const_cast最常用的用途就是删除const属性,如果某个变量在大多数时候是常量,而在某个时候又是需要修改的,这时就可以使用const_cast操作符了。const_cast操作符不能改变类型的其他方面,他只能改变const或volatile,即const_cast不能把int改变为double,但可以把const int改变为int。const_cast只能用于指针或引用。const_cast的用法举例比如:int a=3; const int *b=&a int* c; c=const_cast《int*》(b); *c=4; cout《《a《《*c;这时输出两个4,如果不使用const_cast转换符则常量指针*c的值是不能改变的,在这里使用const_cast操作符,通过指针b就能改变常量指针和变量a的值。
6.4、static_cast操作符:该操作符用于非多态类型的转换,任何标准转换都可以使用他,即static_cast可以把int转换为double,但不能把两个不相关的类对象进行转换,比如类A不能转换为一个不相关的类B类型。static_cast本质上是传统c语言强制转换的替代品。
6.5、reinterpret_cast操作符:该操作符用于将一种类型转换为另一种不同的类型,比如可以把一个整型转换为一个指针,或把一个指针转换为一个整型,因此使用该操作符的危险性较高,一般不应使用该操作符。

dynamic_cast的用法

dynamic_cast 《type-id》 (expression)
该运算符把expression转换成type-id类型的对象。Type-id 必须是类的指针、类的引用或者void*;
如果 type-id 是类指针类型,那么expression也必须是一个指针,如果 type-id 是一个引用,那么 expression 也必须是一个引用。
dynamic_cast运算符可以在执行期决定真正的类型。如果 downcast 是安全的(也就说,如果基类指针或者引用确实指向一个派生类对象)这个运算符会传回适当转型过的指针。如果 downcast 不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个派生类对象)。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。 classB{public:int m_iNum;virtual void foo();};classD:publicB{public:char* m_szName;};void func(B* pb){D* pd1=static_cast《D*》(pb);D* pd2=dynamic_cast《D*》(pb);}在上面的代码段中,如果 pb 指向一个 D 类型的对象,pd1 和 pd2 是一样的,并且对这两个指针执行 D 类型的任何操作都是安全的;但是,如果 pb 指向的是一个 B 类型的对象,那么 pd1 将是一个指向该对象的指针,对它进行 D 类型的操作将是不安全的(如访问 m_szName),而 pd2 将是一个空指针。
另外要注意:B 要有虚函数,否则会编译出错;static_cast则没有这个限制。
这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,详细可见《Inside c++ object model》)中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。

c++关于 dynamic_cast的问题

在实用显示的强制类型
dynamic_cast
的时候,在vc6.0下需要设置,才可以使用。
工程(projece)-》设置(setting)
在里面知道c/c++那个选项。
然后在下面分类中选
c++语言
然后在
勾中下面一个选项
叫允许时间类型信息(rtti)
然后确定就可以使用了。
否则的话,是不可以使用的,运行会出错。

dynamic_cast 的使用的问题

在实用显示的强制类型
dynamic_cast
的时候,在VC6.0下需要设置,才可以使用。
工程(projece)-》设置(setting)
在里面知道C/C++那个选项。
然后在下面分类中选
C++语言
然后在
勾中下面一个选项
叫允许时间类型信息(RTTI)
然后确定就可以使用了。
否则的话,是不可以使用的,运行会出错。

c++中,dynamic_cast是什么作用

dynamic_cast
用于多态性的父子类型对象的指针或引用之间。
class A {
public:
virtual ~A (void) {}
};
class B : public A {};
class C : public B {};
int main (void) {
B b;
A* pa = &b
cout 《《 “pa = “ 《《 pa 《《 endl;
cout 《《 “---- dynamic_cast ----“ 《《 endl;
// pa实际指向B对象,转换成功
B* pb = dynamic_cast《B*》 (pa);
cout 《《 “pb = “ 《《 pb 《《 endl;
// pa没有指向C对象,转换失败
C* pc = dynamic_cast《C*》 (pa);
cout 《《 “pc = “ 《《 pc 《《 endl;//这里应该pc=NULL
}

dynamic_cast 与static_cast的区别

一个动态转换,一个是静态转换。一般情况下使用static_case《类型》
就可以了。
同时,这个只有在高版本的C++编译器中才能识别。
dynamic_cast是试探映射,如dynamic_cast《A》*pB意思是“我希望它是A*,并打算要求它是”。它通常被称为类层次的动态导航。
而static_cast通常可用于类层次的静态导航,无映射变换,窄化变换(会丢失信息)等等,static_cast的应用要广一些,但如前所提到的,在类层次导航变换中我们应该使用前者,因为后者static_cast可能意味着冒险(比如变换时类似于强制转换一样丢失信息)。但是在一个类层次中没有虚函数或者我们确定有其他允许我们安全向下映射的信息则后者static_cast更快一些。

C++中 dynamic_cast转换的是数据类型还是指向的数据类型

father
*p
=
new
father
;
dynamic_cast《son
*》(p);
这个结果是NULL,这点楼上的解释的很清楚啊。
(画图水平有限了,略丑,莫怪,o(╯□╰)o)
你看一下上图,如果你用father
*p
=
new
father
;那么你只新建了S1的空间,但是son的存储空间是S3的大小,有S2大小的存储空间你根本就没有创建,就算你用了dynamic_cast《son
*》(p);来转化指针,但是因为p原本的空间大小根本就没有S2这一半的存在,所以这里会转化失败,返回NULL。
但是你如果是father
*p
=
new son
;这里你新建了S3大小的空间,也就是S1和S2都新建了,但是在因为这时候p是father类型指针,所以这时候p最多的范围是S1大小内存储的东西,虽然你不能使用S2的内容,但是它(S2)毕竟是真实存在的,所以可以用dynamic_cast《son
*》(p);来转化成son的指针,这时候就可以指向S3内的全部了。

C++用dynamic_cast将父类指针转换为子类指针,为什么不一定成功

这个问题牵扯到c++的对象模型。一般认为子类对象大小》=父类对象大小。为什么?因为子类可以扩展父类,可以增加成员变量。如果一个子类增加了成员变量,那么它的对象的内存空间会大于父类对象。这时一个实际指向父类的指针,如果被强制转化为子类对象指针,当使用这个指针时可能会导致越界访问非法内存。相反,为何子类指针可以转换为父类指针?因为父类指针需要的,子类对象都有,不会出现非法内存访问。
这就是dynamic_cast不一定成功的原因。如果一个实际指向子类对象的指针被转换成了父类指针,然后再用dynamic_cast转换回来,一定能成功,而一个实际指向父类对象的指针,被dynamic_cast转换为子类指针,一定会失败。

C++ dynamic_cast关于if判断 有疑惑

if(B *b3=dynamic_cast《B*》(a1))你主要要知道这个if中是用什么作为条件判断的,即里面的执行流程
这个if中作为条件判断的是b3
首先是执行B *b3=dynamic_cast《B*》(a1), 然后再用结果b3作为条件判断,如果转换失败,b3=NULL,
也就相当于if(NULL) 或者if(0),所以条件会为假,执行else下面的语句。