变量概述:
变量根据作用域可以分为局部变量和全局变量,在函数内部定义的变量称为局部变量,在函数外部定义的变量称为全局变量。
如果将全局变量声明在头文件中,并且使用extern关键字修饰,作用是将变量导出,表示在任何通过#include包含该头文件的文件中都可以使用这个全局变量。
使用static修饰的变量称为静态变量,根据作用域又可以分为静态局部变量和静态全局变量,相同之处是两个类型变量的生存周期都是整个程序的生命周期。
一般情况下,静态全局变量的声明放在源文件中,并且不能使用extern关键字导出,静态全局变量的作用域仅限于定义静态全局变量所在的文件内部。
如果在头文件中声明静态全局变量,它在声明的同时会被初始化,如果没有显示的初始化,则会初始化为默认值。如果多个源文件都是用#include包含了定义某个静态全局变量的头文件,那个这个变量在各个源文件中都有一份单独的拷贝,且初始值相同,这些拷贝相互独立,如果修改了某个静态全局变量的值,不会影响其他拷贝。
使用const修饰的变量称为常量型变量,初始化后不能修改。
普通全局变量和常量型全局变量的区别:
全局常量型变量通常在头文件中直接声明和定义,多个源文件引用该头文件不会造成重复定义的问题。
普通全局变量一般在源文件中定义,在头文件中用extern声明,而常量型变量无法采用这种方式,因为在源文件的函数外部定义的常量型变量只限于在当前文件中使用。
i++和++i的区别:
i++:先赋值后加一
++i:先加一后赋值
对于下面的代码:
int m=(i++)+(i++)+(i++) (1)
int n=(++j)+(++j)+(++j) (2)
对于(1)式,先执行加法操作,在执行自增操作。
但是对于(2)式,不同的编译器处理不大相同。
vc编译器:先执行自增操作,在执行加法操作。
gcc编译器:只要有两个完整的操作数,就会立即执行加法操作。所以,先会执行两次自增操作,接着执行一次加法操作,然后就继续执行一次自增操作,最后执行一次加法操作。
C++类型转换操作符:
static_cast
作用:1)替代C风格的类型转换实现基本类型转换
int a=1;
double b=3.2;
int c=static_cast<int>(b);
double d=static_cast(double)(a);
2)用于对象指针之间的类型转换,将父类指针转换为子类指针,将子类指针转换为父类指针。
但是,如果父类指针指向一个父类对象,此时将父类指针转换为子类指针可能是不安全的;如果父类指针指向一个子类对象,则不存在安全性问题。
class Father{};
class Son:public Father{};
Father *a=new Father;
Father *b=new Son;
Son *c=static_cast<Son *>(a); //不安全
Son *d=static_cast<Son *>(b); //安全
dynamic_cast
作用:只能用于对象指针之间的类型转换,可以将父类指针转换为子类指针,也可以将子类指针转换为父类指针,转换结果也可以是引用。
与static_cast的区别:dynamic_cast在将父类指针转换为子类指针的时候,需要对其背后的对象类型进行检查,以保证类型完全匹配,而static_cast不会这样做。只有当一个父类指针指向一个子类对象,并且父类中包含虚函数时,使用dynamic_cast将父类指针转换为子类指针才会成功,否则返回空指针,如果是引用,则抛出异常。
class Father{virtual void father(){}};
class Son:public Father{};
Father * f1=new Father;
Father * f2=new Son;
Son * f2s1=dynamic_cast<Son *>(f1); //转换失败,返回null
Son * f2s2=dynamic_cast<Son *>(f2); //成功
Son &f2s3=dynamic_cast<Son&>(*f1); //转换失败,抛出异常
Son &f2s4=dynamic_cast<Son&>(*f2); //成功
const_cast
作用:在转换过程中增加或者删除const属性。一般情况下,无法将常量指针直接赋值给普通指针,但是可以通过const_cast移除常量指针的const属性,实现const指针到非const指针的转换。
class A{};
const A *a=new A;
A *b=const_cast<A *>(a);
reinterpret_cast
作用:将一种类型的指针直接转换为另一种类型的指针,不论两个类型之间是否有继承关系。此外,还可以把一个指针转换为一个整数,也可以把一个整数转换为一个指针。还经常用在不同函数指针之间的转换。
class A{};
class B{};
A *a=new A;
B *b=reinterpret_cast<B *>(a);