inheritWord下载.docx
《inheritWord下载.docx》由会员分享,可在线阅读,更多相关《inheritWord下载.docx(11页珍藏版)》请在冰豆网上搜索。
![inheritWord下载.docx](https://file1.bdocx.com/fileroot1/2023-1/1/64496771-e46a-47cf-82c5-9eb59e453c46/64496771-e46a-47cf-82c5-9eb59e453c461.gif)
Derived*pd=&
base;
//Error,派生类指针指向基类对象;
pb->
show();
//Ok,但输出derived;
print();
//Error.不可调用仅派生类有的方法;
typedefvoid(Derived:
:
*Pderived)();
Pderivedpmend=&
Base:
show;
//Ok,基类成员的指针赋值给派生类成员的指针
(derived.*pmend)();
//使用派生类成员指针
typedefvoid(Base:
*Pbase)();
Pbasepmenb=&
Derived:
//Error.派生类成员的指针赋值给基类成员的指针
}
reinterpret_cast,C-stylecastorfunction-stylecast
dynamic_cast
classB{/*......*/virtualvoidf();
classV{/*......*/virtualvoidg();
classX{/*novirtualfunctions*/};
classD:
publicB,publicvirtualV,publicvirtualX{
//...
};
voidfoo(D&
d)
{
B*pb=&
d;
D*p1=(D*)pb;
//ok,unchecked
D*p2=dynamic_cast<
D*>
(pb);
//ok,run-timechecked
V*pv=&
D*p3=(D*)pv;
//error:
cannotcastfromvirtualbase
D*p4=dynamic_cast<
(pv);
X*px=&
D*p5=(D*)px;
D*p6=dynamic_cast<
(px);
can'
tcastfromnon-polymorphictype
}
1.reinterpret_cast可以转换任意一个32bit整数,包括所有的指针和整数。
可以把任何整数转成指针,也可以把任何指针转成整数,以及把指针转化为任意类型的指针,威力最为强大!
但不能将非32bit的实例转成指针。
总之,只要是32bit的东东,怎么转都行!
2.static_cast和dynamic_cast可以执行指针到指针的转换,或实例本身到实例本身的转换,但不能在实例和指针之间转换。
static_cast只能提供编译时的类型安全,而dynamic_cast可以提供运行时类型安全。
举个例子:
3.class
a;
class
b:
c。
4.上面三个类a是基类,b继承a,c和ab没有关系。
5.有一个函数void
function(a&
a);
6.现在有一个对象是b的实例b,一个c的实例c。
7.function(static_cast<
a&
>
(b)可以通过而function(static<
(c))不能通过编译,因为在编译的时候编译器已经知道c和a的类型不符,因此static_cast可以保证安全。
8.下面我们骗一下编译器,先把c转成类型a
9.b&
ref_b
=
reinterpret_cast<
b&
c;
10.然后function(static_cast<
(ref_b))就通过了!
因为从编译器的角度来看,在编译时并不能知道ref_b实际上是c!
11.而function(dynamic_cast<
(ref_b))编译时也能过,但在运行时就失败了,因为dynamic_cast在运行时检查了ref_b的实际类型,这样怎么也骗不过去了。
12.在应用多态编程时,当我们无法确定传过来的对象的实际类型时使用dynamic_cast,如果能保证对象的实际类型,用static_cast就可以了。
至于reinterpret_cast,我很喜欢,很象c语言那样的暴力转换:
)
13.dynamic_cast:
动态类型转换
14.static_cast:
静态类型转换
15.reinterpret_cast:
重新解释类型转换
16.const_cast:
常量类型转换
17.synamic_cast一般用在父类和子类指针或应用的互相转化;
18.static_cast一般是普通数据类型(如int
m=static_cast<
int>
(3.14));
19.reinterpret_cast很像c的一般类型转换操作
20.const_cast是把cosnt或volatile属性去掉
21.
22..
23.
24.泛型(Generic
Types)
25.
26.
float
f
12.3;
27.
float*
pf
&
f;
28.
//
static
cast<
29.
成功编译,
n
12
30.
int
static_cast<
(f);
31.
错误,指向的类型是无关的(译注:
即指针变量pf是float类型,现在要被转换为int类型)
//int*
pn
int*>
(pf);
32.
//成功编译
33.
void*
pv
void*>
34.
//成功编译,
但是
*pn2是无意义的内存(rubbish)
35.
int*
pn2
36.
37.
//错误,编译器知道你应该调用static_cast<
38.
//int
i
39.
*pn
实际上是无意义的内存,和
*pn2一样
40.
pi
简而言之,static_cast<
将尝试转换,举例来说,如float-到-integer,而reinterpret_cast<
简单改变编译器的意图重新考虑那个对象作为另一类型。
41.
42.指针类型(Pointer
43.
44.class
CBaseX
45.
{
46.
public:
47.
x;
48.
CBaseX()
x
10;
}
49.
void
foo()
printf("
CBaseX:
x=%d/n"
x);
50.
51.
CBaseY
52.
53.
54.
y;
55.
py;
56.
CBaseY()
y
20;
py
57.
bar()
CBaseY:
y=%d,
*py=%d/n"
y,
*py);
58.
59.
60.
CDerived
public
CBaseX,
61.
62.
63.
z;
64.
情况1:
两个无关的类之间的转换
65.
66.
67.
Convert
between
CBaseX*
and
CBaseY*
68.
和
CBaseY*之间的转换
69.
pX
new
CBaseX();
70.
Error,
types
pointed
to
are
unrelated
71.
错误,
类型指向是无关的
72.
CBaseY*
pY1
CBaseY*>
(pX);
73.
Compile
OK,
but
pY2
is
not
CBaseX
74.
不是CBaseX
75.
76.
System
crash!
!
77.
系统崩溃!
78.
pY2->
bar();
正如我们在泛型例子中所认识到的,如果你尝试转换一个对象到另一个无关的类static_cast<
将失败,而reinterpret_cast<
就总是成功“欺骗”编译器:
那个对象就是那个无关类。
79.
80.情况2:
转换到相关的类
81.
82.
1.
CDerived*
pD
CDerived();
83.
2.
%x/n"
(int)pD);
84.
3.
85.
4.
->
CDerived*
86.
//成功编译,隐式static_cast<
转换
87.
5.
pD;
88.
6.
(int)pY1);
89.
现在
pD1
pD
90.
7.
CDerived*>
(pY1);
91.
8.
(int)pD1);
92.
9.
93.
10.
reinterpret_cast
94.
不是
95.
11.
(pD);
96.
12.
(int)pY2);
97.
13.
98.
14.
无关的
99.
15.
pY3
CBaseY();
100.
16.
(int)pY3);
101.
成功编译,尽管
只是一个
"
新
CBaseY()"
102.
17.
pD3
(pY3);
103.
18.
(int)pD3);
----------------------
输出
---------------------------
104.
392fb8
105.
392fbc
106.
107.
108.
390ff0
109.
390fec
110.
注意:
在将CDerived*用隐式
转换到CBaseY*(第5行)时,结果是(指向)CDerived*(的指针向后)
偏移了4(个字节)(译注:
4为int类型在内存中所占字节数)。
为了知道static_cast<
实际如何,我们不得不要来看一下CDerived的内存布局。
111.
112.CDerived的内存布局(Memory
Layout)
viewplaincopytoclipboardprint?
1.如图所示,CDerived的内存布局包括两个对象,CBaseX
CBaseY,编译器也知道这一点。
因此,当你将CDerived*
转换到
CBaseY*时,它给指针添加4个字节,同时当你将CBaseY*转换到CDerived*时,它给指针减去4。
然而,甚至它即便不是一个CDerived你也可以这样做。
2.当然,这个问题只在如果你做了多继承时发生。
在你将CDerived转换
到
CBaseX时static_cast<
是没有区别的。
3.
4.情况3:
void*之间的向前和向后转换
5.
6.因为任何指针可以被转换到void*,而void*可以被向后转换到任何指针(对于static_cast<
转换都可以这样做),如果没有小心处理的话错误可能发生。
7.
8.
9.
10.
11.
12.
pY
+
4
13.
(int)pY);
14.
pV1
pY;
pY
15.
(int)pV1);
16.
pD2
pY,
但是我们预期
-
17.
(pV1);
18.
(int)pD2);
19.
系统崩溃
20.
pD2->
---------------------------
22.
24.
一旦我们已经转换指针为void*,我们就不能轻易将其转换回原类。
在上面的例子中,从一个void*
返回CDerived*的唯一方法是将其转换为CBaseY*然后再转换为CDerived*。
26.但是如果我们不能确定它是CBaseY*
还是
CDerived*,这时我们不得不用dynamic_cast<
或typeid[2]。
28.注释:
29.1.
dynamic_cast<
,从另一方面来说,可以防止一个泛型CBaseY*
被转换到CDerived*。
30.2.
需要类成为多态,即包括“虚”函数,并因此而不能成为void*。
31.参考:
32.1.
[MSDN]
C++
Language
Reference
--
Casting
33.2.
Nishant
Sivakumar,
Basics
Use
casts
in
your
VC++.NET
programs
34.3.
Juan
Soulie,
Tutorial:
Type
使用标准C++的类型转换符:
static_cast、dynamic_cast、reinterpret_cast、和const_cast。
1static_cast
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。
它主要有如下几种用法:
①用于类层次结构中基类和子类之间指针或引用的转换。
进行上行转换(把子类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
不需要有虚函数
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。
这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
static_cast不能转换掉expression的const、volitale、或者__unaligned属性。
2dynamic_cast
用法:
dynamic_cast<
type-id>
(expression)
该运算符把expression转换成type-id类型的对象。
Type-id必须是类的指针、类的引用或者void*;
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
classB{
intm_iNum;
virtualvoidfoo();
classD:
publicB{
char*m_szName[100];
voidfunc(B*pb){
D*pd1=static_cast<
D*>
D*pd2=dynamic_cast<
在上面的代码段中,如果pb指向一个D类型的对象,pd1和pd2是一样的,并且对这两个指针执行D类型的任何操作都是安全的;
但是,如果pb指向的是一个B类型的对象,那么pd1将是一个指向该对象的指针,对它进行D类型的操作将是不安全的(如访问m_szName),
而pd2将是一个空指针。
dynamic_cast使用时要有虚函数,否则会编译出错;
static_cast则