类型转换
一、Const_cast
去除常量特性
二、Static_cast
普通类型转换和类继承的父指针到子类指针的转换(引用一样)
注意:不能用于对象本身,只转换不进行运行时类型检查
不能进行的转换:
1、*p -- > int
2、Aobj ---> Bobj
3、Const --> non-const
总的来说,没有意义的转化,该转换都不能做到
三、Reinterpret_cast
转换类型:
1、无关的指针到指针(类型在继承层次中不相关也可以)
2、无关的引用到引用(类型无关)
例如:
class x{};
class y{};
x X;
y Y;
x* px;
y* py;
px = reinterpret_cast
py = reinterpret_cast
y& ry = Y;
x& rx = reinterpret_cast
3、指针到int
4、Int到指针
5、函数指针
注意:此类型也不会进行类型检查
四、Dynamic_cast
继承层次的指针,引用进行转换。运行时进行底层对象类型检查。
注意:由于运行时类型信息存在对象的Vtable中,因此类中必须有一个虚函数。
引用
1、 必须在创建时初始化
2、 引用指向一个const值,就可以创建未命名值的引用,否则编译错误
例如:
const int& ref = 5; //正确
int& ref = 5; //错误
3、 引用的修改误区(引用指向不可更改)
引用一旦创建它的指向就不能在修改,可以改变它的值(即指向的变量的值)。
例如: int a = 10, b = 20;
Int & ra = a;
cout << ra << endl;
cout << a << endl;
ra = b; //改变只是ra的值也就是a的值,并不会改变指向
cout << ra << endl;
cout << a << endl;
当你写出如下代码来绕过这条限制时:
Ra = &b; //错误
//表达式的两侧的类型不匹配。右侧&b是一个指针,左侧是int变量的引用,而不是指针的引用。
当引用给引用又会如何:
Int &rb = b;
ra = rb; //依然是赋值操作,而不会改变ra指向。
4、 指针的引用,引用的指针,引用的引用:
指针的引用声明方式:类型+*+&+refname = pointName
例如:
int* pInt = &a;
int* &rPInt = pInt;
cout << *rPInt <
int& *pra = ra; //不能声明引用的指针
int& &rra = ra; //不能声明引用的引用
5、 取引用的地址和取引用所指变量的地址是一样的;
例如:
cout << &ra <
cout << &a <
6、 引用数据成员
当数据成员是引用时必须依靠成员初始化列表完成,不能通过构造函数体中完成。这样的原因是:如果引用不指向其他变量就无法存在。
例如:
class x
{
public:
x(const int& num_ = 10):num(num_)
{
cout << "x's " << num << endl;
}
private:
const int #
};
7、 引用参数
当函数参数为引用参数时,对被调用函数的参数修改就会修改外部调用代码的实参。因为可以把这种现象看成是实参的别名,就像上述引用的讨论一样。引用参数提高了程序的效率,因为减少了拷贝构造的调用操作。
引用参数带来的好处:
1、 效率:当复制大对象时花费很长时间,传递对象或指针会节省时间。
2、 正确性:不是所有的对象都允许传值,即使传值,也不一定就能正确的完成深拷贝操作。支持此操作,动态分配的对象必须提供定制的拷贝构造。
运用时机:对于内置类型,不需要修改实参,就应使用传值方式。其他都可以使用引用。
8、 引用返回值
当返回值是引用时,引用所对应的变量即将销毁,它所指向的数据将会出现问题,因为变量的生命周期已经结束。
运用时机:
1、当返回值是引用时,一般是出于效率的考虑,这样可以避免不必要的复制操作,只有当前对象在函数结束后依然存在的情况下。
2、为了实现链式操作
9、 与指针的比较:
1、 使程序清晰明了
2、 代码安全(不存在无效的引用)
准则:除非动态分配或在其他改变或释放指针指向的值,否则都应使用引用而不是指针
Const 应用事项
const修饰变量(必须初始化)
1、定义常量
例如:const int arraysize = 10;
2、指针常量,常量指针
当const和类型同在*的左侧时:(常量指针)
如: Const + 类型 + * + point 或 类型 + const + * + point
指针指向可以改,指针指向的值是不能通过指针进行修改。
当 const 紧靠变量的左侧时:(指针常量)
指针指向不可改,指针指向的值是可以通过指针进行修改。
3、const引用
Int a = 50;
Const int& ra = a; //const int& 等价 int const&
ra = 4; //不能通过引用修改a,可以直接修改a;
a = 100;
cout << ra <
总结:修饰的目标在于 const 在 * 的左边,还是右边。
左边修饰的是指针的内容,右边修饰的是指针的指向
const修饰函数
const对象只能调用const成员函数
非const对象都两者都可调用
const成员函数只能调用const成员函数
const修饰参数
防止参数被修改(代表输入参数)
Const引用作参数,既提高效率,有防止修改实参
Const修饰返回值
Static使用
Static内部连接符(匿名命名空间也可达到此效果)
只在声明它的当前编译单元可以使用
Const,typedef默认都是内部连接
Extern外部连接符
多个编译单元都可使用
Const,typedef默认都是内部连接,可以是extern指定外部连接。
把一个名字指定为外不连接时,编译器把它当作声明来对待。所以编译器不会分配空间,因此,必须提供另外的定义。
Static变量(记忆性变量)
函数中的static变量,只初始化一次,下次用上次的值。
类中的static变量(准侧:采用对象内维护变量的状态)
与类关联而不是与类对象关联,对象拥有的是副本
static初始化
在mian前执行,默认初始化零值,类中的也是一样。
准侧:不同源文件中非局部变量初始化顺序不确定。
Static函数没有this指针只能访问静态成员