最近温习的一些C++基础知识,记性不好,看了忘,忘了看,来个简要小记好了。
static_cast *
dynamic_cast *
reinpreter_cast *
const_cast *
参考 *
这是标准C++中的四个类型转换符,是C风格的强制类型转换的推荐替代物,如(T) expression 或 T (expression)。
static_cast
用法 :static_cast type-id ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的(这也是引出dynamic_cast * 的原因)。
- 用于基本数据类型之间的转换,如把int转换成double,把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
- 把空指针转换成目标类型的空指针。
- 把任何类型的表达式转换成void类型。 把non-const转换成const,相反的操作由const_cast * 完成。 注意 : static_cast 不能转换掉expression的const、volitale、或者__unaligned属性。
例子 :
class CBaseX
{
int x;
}
class CBaseY
{
int y;
int* py;
}
class CDerived : public CBaseX, public CBaseY
{
}
CDerived的内存布局(Memory Layout)
如图所示,CDerived的内存布局包括两个对象,CBaseX 和 CBaseY,编译器也知道这一点。因此:
当你将CDerived 用static_cast* 转换到 CBaseY时,它给指针添加4个字节,同时当你将CBaseY用static_cast * 转换到CDerived时,它给指针减去4。 *然而,甚至它即便不是一个CDerived你也可以这样做,此时static_cast * 将是不安全的。当然,这个问题只在如果你做了多继承时发生。 在你将CDerived转换 到 CBaseX时static_cast 和reinterpret_cast * 是没有区别的。 因为基类不是“虚”类,所以不能使用dynamic_cast * ;如果是“虚”类,则情况与 static_cast 同,且下行转换时有安全检查,转换失败返回NULL。
dynamic_cast
用法 * gt( expression )该运算符把expression转换成type-id类型的对象。type-id必须是类的指针、类的引用或者void *;
- 如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。
- 通过RTTI来判断类型转换的合法性,需要类成为多态,即包括“虚”函数,因此不能用于转换void*。
- 主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换(不相关的类相互转换,试验过,直接返回NULL)。
- 由于要动态判别,实现相当慢,尽量避免使用。
在类层次间进行上行转换时, dynamic_cast 和 static_cast 的效果是一样的;在进行下行转换时, dynamic_cast 具有类型检查的功能,比 static_cast 更安全。深入讨论RTTI,请参见 [4]
reinpreter_cast
用法
type-id 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。 该运算符的用法比较多。
const_cast
用法
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。 常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。
参考
gtis actually doing 1.
gt揭密 1.
C++箴言:将强制转型减到最少 1.
如何在运行时确定对象类型(RTTI) 1.