1、内部名称
所有的变量和函数,在编译的时候都会生成一个内部名称,用以识别。这就能够说明重载函数以及不同类的同一函数的区分问题。
2、变量及其初始化
(1)变量是内存单元的别名,取变量名就是取内存单元中存放的值。
(2)静态变量存放在程序的静态数据区,在程序进入mian()之前创建,在main()之后销毁。在代码中是没有机会初始化全局变量的。声明和定义需要在源文件的开头进行。
(3)函数内的static局部变量和类中的static变量也会被移动到程序的静态数据区中。
(4)程序的静态数据区中的数据都会有默认值,但是自动变量不会有默认值的。局部变量的初始化,类中非静态数据成员的初始化是程序员的责任,而不是编译器的责任。
(5)全局变量声明时,应该直接进行初始化,即extern后 ,直接赋值。
3、基本数据类型和内存映像
(1)转至Vast_Sea的博客
而且这个也与机器、OS、编译器有关,比如同样是在32bits的操作系统系,VC++的编译器下int类型为占4个字节;而tuborC下则是2个字节。所以int,long int,short int的宽度都可能随编译器而异
16位编译器
char :1个字节
char*(即指针变量): 2个字节
short int : 2个字节
int: 2个字节
unsigned int : 2个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节32位编译器
char :1个字节
char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节64位编译器char :1个字节
char*(即指针变量): 8个字节
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 8个字节
long long: 8个字节
unsigned long: 8个字节
注意char*在不同操作系统中占的字节数。32位系统指针的长度为4字节(即一个内存单元的大小)。64系统的指针的长度为8字节.
4、虚函数
(1)把基类的成员函数设为virtual,其派生类的相应的函数也会自动变为虚函数。
(2)指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。
(3)虚函数是如何做到因对象的不同而调用其相应的函数的呢?
由于A::fun()和A::fun2()是虚函数,所以&A::fun和&A::fun2获得的不是函数的地址,而是一段间接获得虚函数地址的一段代码的地址,我们形象地把这段代码看作那段CallVirtualFun。编译器在编译时,会提供类似于CallVirtualFun这样的代码,当你调用虚函数时,其实就是先调用的那段类似CallVirtualFun的代码,通过这段代码,获得虚函数地址后,最后调用虚函数,这样就真正保证了多态性。同时大家都说虚函数的效率低,其原因就是,在调用虚函数之前,还调用了获得虚函数地址的代码。
5、类型转换
(1)类型转换并没有改变原来的类型和值,而是生成了新的临时变元,其类型为目标类型,将临时变元赋予目标变量。
(2)派生类转化为基类,有内存截断,但是是安全的;而指针直接赋予,就是直接把派生类地址赋予基类的指针。
(3)C++中任何类型的指针都可以指派给void,反过来不行。
(4)强制转化导致的安全问题
基本数据类型的指针转换一般会造成内存截断和扩张,改变了编译器对指针所指向内存单元的解释方式。
- 比如
double d2 = 1000.25;
int pInt= (int )&d2;
int i1 = 100;
double pdb1 = (double ) &i1;
这里面, pInt获取到的是d2前4个字节的内容,不可预料。而pdb1 获取到的是4个字节的i1 + 扩张的4个字节的,不可预料。
不可以把基类对象直接转换为派生类对象,反过来是可以的。
6、常量表达式求值的时候,不用等到运行的时候求,在编译的时候就可以求值。————定义为可以在编译时就求值的表达式。(但是在字符串常量,const常量、都要分别运行时的存储空间,所以。。。。。)
7、判断两个浮点型数据的是否相等时,采用if(abs(a-b)