16.}
变量作用域:
变量有效范围,有四种:
文件作用域filescope函数作用域functionscope
块作用域blockscope函数原型作用域functionprototypescope
递归函数:
函数体中,直接或间接调用函数本身的函数。
变量的存储类别:
外部、局部(相对于函数而言)
全局变量(也即外部变量)
静态局部变量(static)
自动变量(不加static的局部变量)
寄存器变量(register)存放在CPU中,而非内存中,这样在使用时就省去了从内存中载入寄存器的过程。
但只是建议性的,优化编译系统自动识别使用频繁的变量,从而自动将变量放入寄存器中。
extern声明的外部变量
即提前引用申明,表示该变量是将在下面定义的全局变量或在其它文件中定义(本文件中不用extern,引用该变量的外部文件用extern进行声明)
static声明的静态外部变量
只能被本文件使用,而不能被外部文件使用的全局变量,这样不同文件中的全局变量不会相互干扰,为程序模块化、通用化提供方便。
注:
全局变量也是静态存储的。
内部函数与外部函数
内部函数:
static声明,文件内使用
外部函数:
另一个文件里extern声明,表示是其它文件的函数,extern可以省略
宏定义
#definePI3.14定义符号常量
#defineArea(a,b)a*b//定义函数功能,下面当作函数来用。
#include'iostream'区别
<>在系统目录寻找,找不到报错
''在当前目录寻找,找不到报错
字符数组
(1)charstr[]="iamhappy";
数组长度为11,而非10,因为后面有一个'\0'
(2)charstr[]={'i','a','m','h','y'}
数组长度为5,系统不会自动为其在后面加'\0'
因此,
(1),
(2)是不同的
输出字符数组:
cout<string类
字符数组是C中的处理方式,C++中用string类,#include
字符串变量中不会存放'\0',只存放字符串本身,故stringstr="hello";的长度为5,要注意。
字符串变量存储的实际是字符串的指针,4个字节,
sizeof(string)=4;
stringname[]={"i","am","happy"};sizeof(name)=3*4=12;
变量与指针:
int*p=&i;//int型指针变量,定义时的*只是表示指针类型
p是指针变量,其值是变量i的地址,*p则是存储单元,*&a与*p同,都表示变量a
指向数组的指针
inta[10]={};
int*p;
p=&a[0];//与下面等价,都指向数组第一个元素,因为数组名本身就是表示数组的地址
p=a;
*************************
*p++相当于*(p++),先得到*p的值,p再++移到下一个元素
(*p)++则是使*p的值+1
二维数组的指针表示:
*(*(p+i)+j)表示a[i,j]
*************************
int(*p)[n]p为指向含n个元素的数组的指针
int*p[n]定义指针数组P
函数指针指向函数的指针,主要用作形参
intmax(int,int);
int(*p)(int,int);
p=max;赋值(地址)
p(1,2)//调用
引用
inta=10;
int&b=a;b是对a的引用
引用传递,引用型变量作为函数形参
[cpp]viewplaincopy
01.//值会改变
02.main{
03.inti=5,j=6;
04.swap(i,j)
05.}
06.voidswap(int&a,int&b)//这里的&不是“a的地址”,而是指“a是一个引用型变量”,&是个声明符
07.{
08.inttemp;
09.temp=a;
10.a=b;
11.b=temp;
12.}
传递变量地址:
形参是指针变量,实参是变量地址,这种虚实结合的方法仍然是“值传递”方式,只是实参的值是变量地址而已。
[cpp]viewplaincopy
01.//值会改变
02.main()
03.{
04.inti=5,j=6;
05.swap(&i,&j)
06.}
07.voidswap(int*p1,int*p2)//这里的*号也只表示是指针类型
08.{
09.inttemp;
10.temp=*p1;
11.*p1=*p2;
12.*p2=temp;
13.}
结构体变量struct
作函数参数时有三种形式
(1)用结构体变量名作形参
这时形参要开辟内存单元,实参中全部内容通过值传递方式一一传递给形参,时空开销大,效率低
(2)用指向结构体变量的指针作形参,只有四个字节
voidprinted(student*p)
{
cout<num;
}
(3)用结构体变量的引用变量作形参
Studentstu;
print(stu);
voidprint(Student&stu)
{
cout}
newdelete动态内存分配
new类型(初值),返回地址,分配失败返回NULL
float*f=newfloat(3.14);
int*i=newint(6);
int*k=newint[5][4];//数组
delete变量deletef;deletei;
数组delete[]k;
Enum枚举类型
声明枚举类型enumweekday{sun,mon,tue,wed,thu,fri,sat};
定义枚举变量weekdayworkday,week_end;
变量赋值:
workday=mon;或workday=weekday
(2);
枚举常量对应值从0开始,0,1,2,3..
typedef声明新类型
typedefintINTEGER,相当于为int起了个别名,下面程序中就可以直接用INTEGER作int用了
主要为了方便系统移植,如longint在VC中4个字节,在GCC中占8个字节,直接用int的话可能会溢出,用INTEGER就不用担心了,只要把ypedefintINTEGER声明语句一改就行
运算符重载
方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现响应运算。
即运算符重载是通过定义函数实现的,运算符重载实际上是函数重载。
格式:
函数类型operator运算符名称(形参表列)
{对运算符的重载处理}
例如:
将+用于Complex类(复数)的加法运算,函数原型如下:
Complexoperator+(Complex&c1,Complex&c2);
注:
operator是关键字,operator+就是函数名,可以描述为:
函数operator+重载了运算符+
整数加可以想象为调用如下函数
intoperator+(inta,intb)
{returna+b;}
[cpp]viewplaincopy
01.#include
02.usingnamespacestd;
03.classComplex
04.{
05.public:
06.Complex(){real=0;imag=0;}
07.Complex(doubler,doubler){real=r;imag=i;}
08.Complexoperator+(Complex&c2);//声明重载运算符的函数
09.voiddisplay();
10.private:
11.doublerea;
12.doubleimag;
13.};
14.ComplexComplex:
:
operator+(Complex&c2)//定义重载运算符的函数
15.{
16.Complexc;
17.c.real=real+c2.real;
18.c.imag=imag+c2.imag;
19.returnc;
20.}
21.voidComplex:
:
display()
22.{
23.cout<24.}
25.intmain()
26.{
27.Complexc1(3,4),c2(5,-10),c3;
28.c3=c1+c2;//运算符+用于复数运算
29.cout<<"c1=";c1.display;
30.cout<<"c2=";c2.display;
31.cout<<"c1+c2=";c3.display;
32.return0;
33.}
34.运行结果:
35.c1=(3,4i)
36.c2=(5,-10i)
37.c1+c2=(8,-6i)
重载运算符的规则
(1)C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
(2)C++允许重载绝大部分的运算符
(3)重载不能改变运算符运算对象的个数
(4)重载不能改变运算符的优先级别
(5)重载不能改变运算符的结合性
(6)重载运算符的函数不能有默认的参数
(7)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少一个是类对象(或类对象的引用)。
也就是说参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。
(8)用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载
(9)应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能,否则不易使人理解程序
(10)运算符重载函数可以是类的成员函数,也可以是类的友元函数,还是计费成员函数也非友元函数的普通函数。