新学到的,针对类的转换符:
dynamic_cast, static_cast, reinterpret_cast, const_cast
这些转换符的使用,是当函数不是类的成员函数时,但需要调用之,并且传入的参数是对象时。
dynamic_cast: 使用内部的运行时类型信息数据结构,完成类型检查和转换操作。它可以完成upcasting,和downcasting,
如果转换失败,它会返回一个0,或者抛出一个std::bad_cast错误。
注意:当基类存在虚函数时,才能使用dynamci_cast。而且必须包含《typeinfo》头文件。而且类型的转换必须在同一个层次结构中。
static_cast:不进行运行时检查,而且做转换的基类和派生类不必非要在同一个多态的类层次结构中。它在对不在同一个类层次结构中的
类型进行静态的类型检查。
注意:如果要从基类向下强制转换到派生类,这种转换并非总是安全的。强制转换可能产生一个不同的,可能无效的地址。
例子:
class C : public A, public B{}
B *pb;
// pb is somehow initialized
..........
C *pc = static_cast
如果pb指向一个C类型对象,强制转换可以正常工作。如果它指向一个B类型的对象,可以强制转换,但地址不对。类似的,如果指针指向
一个基类对象,而我们用派生类指针访问不存在的派生类对象的成员,就可能造成不可预知的后果。《如果不能确定强制转换是否安全,
可以使用dynamic_cast对指针或引用进行向下的强制转换,然后检查结果是否正确》
reinterpret_cast:主要是为了取代C风格的强制类型转换用法,没有太大的使用。
const_cast: 主要是为了去掉对象的const属性,或者说是在const成员函数中,将this指针转换成对象本身的指针)。
为什么要这么做呢? 我们常看到: 一个对象被定义成const属性,那么它就只能去调用const成员函数,而对于一些类的成员变量是
用来管理对象的,并不是给用户使用的。它们处理用户不关心的隐藏数据,而且它们必须这样做,而不考虑对象是不是const。
例如:
class AnObject
{
int value;
int repetition;
public:
AnObject(int v) : value(v), repetition(0) {}
void report() const;
}
void AnObject::report() const
{
const_cast
std::cout<< repetition << std::endl;
}
int main()
{
const AnObject a(123);
a.report();
a.report();
return 0;
}
如果report成员函数不是const的,程序就不能为const类对象使用该成员函数。A::report数据本身需要递增repetition数据成员,
这种操作在const成员函数中不允许,因为const函数不能修改数据值。为了强制去掉对象的const属性,以便完成递增操作,函数
使用了const_cast运算符把this指针强制转换成非const类对象的指针。
一个另外的解决办法就是将成员变量声明为mutable,mutable表示数据绝不具有const属性,但是这个类可以被实例化成一个
const对象。如果变量被声明为mutable那么const成员函数才可以修改数据成员,一个强大的功能!!