C++程序设计学习要点

来源:互联网 发布:淘宝 大码女装冬季 编辑:程序博客网 时间:2024/06/06 10:47

1   基本知识

1.1 C++初步知识

C++ VS C

l    功能增强

l    面向对象(类)

1.2 C++程序结构

物理级别

源文件(.cpp)

头文件(.h)

代码级别

预定义 #define

预包括 #include “用户文件

#include <系统文件>

外部变量[static/extern] int iVar

主函数 int main ()

{

预调用函数申明 int sub_fun(int x, int y)

常量定义 #define PI 3.1415926

const int iCon = 99

变量定义 [auto/static/register/extern] int iVar

 

控制语句 if (){}

              do{}while

              for(){}

语句块     {x = y;}

调用语句 sub_fun(1,2)

返回语句 return 0

}

类定义级别

Class aCs()

 

1.3 数据类型和表达式

1.3.1 概述图

 

基本类型  

整型   

短整型(short int)

                            整型(int)

                            长整型(long int)

                 字符型(char)

                 浮点型

单精度型(float)

                            双精度型(double)

                            长双精度型(long double)

                 布尔型(bool)

                 构造类型

枚举类型(enum)

                            数组类型

                            结构体类型(struct)

                            共用体类型(union)

                            类类型(class)

                 指针类型

                 引用类型

                 空类型(void)

 

1.3.2 常量

数值常量

10进位Long Int标示 18L

8进制标示 022

16进制标示 0x12

字符常量

转义字符 /n,/0

字符串常量

 

符号常量

预定义,#define PRICE 30

 

1.3.3 变量

l    变量名规范:标识符只能由字母、数字和下划线3种字符组成,且第一个字符必须为字母或下划线。

l    大小写敏感;

l    赋初始值:float a,b=5.78*3.5,c=2*sin(2.0)

l    Const常变量,#define命令定义符号常量是C语言所采用的方法,C++把它保留下来是为了和C兼容。C++的程序员一般喜欢用const定义常变量

1.3.4 运算符汇总

(1) 算术运算符

    +()-() *() /()  %(整除求余)++(自加) --(自减)

(2) 关系运算符

(大于)(小于)  ==(等于)>=(大于或等于)<=(小于或等于)!=(不等于)

() 逻辑运算符

&&(逻辑与) ||(逻辑或)  (逻辑非)

() 位运算符

<<(按位左移)  >>(按位右移)  (按位与)  |(按位或)     (按位异或)  ~(按位取反)

() 赋值运算符 (=及其扩展赋值运算符)

左值:所有变量都是左值。

右值:变量和常变量、表达式、函数等可以。

() 条件运算符 (?:)

() 逗号运算符 ()

返回最后一个表达式的值

() 指针运算符 (*)

(9)   引用运算符和地址运算符 ()

(10) 求字节数运算符(sizeof)

(11) 强制类型转换运算符( (类型) 或类型( )

intx int (x)

(12) 成员运算符 .

(13) 指向成员的运算符 ->

(14) 下标运算符 ([ ])

(15) 其他 (如函数调用运算符())

1.3.5 其他运算符特性

算术表达式和运算符的优先级与结合性

优先级

结合性分为左结合和右结合

 

混合运算和类型隐式转换

类型向上自转化

自增、自减运算符

b = 1

a= ++b,先加1后用,a=2

a= b++,先用后加1a=1

复合赋值运算符

+=,-=,*=,/=,%=,<<=,>>=,&=,∧=,|

一是为了简化程序,使程序精炼,二是为了提高编译效率(这样写法与逆波兰式一致,有利于编译,能产生质量较高的目标代码)

 

 

2   面向过程的程序设计

2.1 程序设计初步

程序=算法+数据结构

 

2.1.1 C++程序结构

#include <iostream>            //预处理命令

using namespace std;           //在函数之外的声明部分

int a=3;                       //在函数之外的声明部分

int main( )                     //函数首部

{ float b;                     //函数内的声明部分

      b=4.5;                       //执行语句

      cout<<a<<b;                  //执行语句

      return 0;                    //执行语句

}

 

1. 声明语句

2. 执行语句

(1) 控制语句

(2) 函数和流对象调用语句

(3) 表达式语句

3. 空语句

;

4. 复合语句

{}复合语句中最后一个语句中最后的分号不能省略

赋值语句

2.1.2 C++的输入与输出

#include <iostream>

cout<<表达式1<<表达式2<<……<<表达式n<<endl;

cin>>变量1>>变量2>>……>>变量n;

 

C保留函数:

getcharputchar

 

scanf(格式控制,输出表列)

printf(格式控制,输出表列)

 

2.1.3 关系运算和逻辑运算

<     (小于)       

<=    (小于或等于)     优先级相同 ()

>     (大于)       

>=    (大于或等于)      

==    (等于)

=  (不等于)          优先级相同 ()

 

优先级定义

4种高于后两种

关系运算符的优先级低于算术运算符。

关系运算符的优先级高于赋值运算符。

 

2.2 函数与预处理

2.2.1 函数实现

l    类型标识符 函数名([void]){声明部分;语句;}

 

l    值传递:参变量对形参变量的数据传递是值传递,即单向传递,只由实参传给形参,而不能由形参传回来给实参。

地址传递可以用引用或静态变量等形式实现。

 

l    函数声明与原型

(1) 如果使用库函数,一般还应该在本文件开头用#include命令将有关头文件包含到本文件中来。

(2) 如果使用用户自己定义的函数,而该函数与调用它的函数(即主调函数)在同一个程序单位中,且位置在主调函数之后,则必须在调用此函数之前对被调用的函数作声明

 

l    内置函数

内置函数(inline function),又称内嵌函数,编译器会转化为硬代码实现

规模较小而又被频繁调用的简单函数,才适合于声明为inline函数。

函数作inline声明,只是程序设计者对编译系统提出的一个建议,也就是说它是建议性的,而不是指令性的。并非一经指定为inline,编译系统就必须这样做。编译系统会根据具体情况决定是否这样做

 

l    函数的重载

 

l    函数模板

建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表

template<typename T>   //模板声明,其中T为类型参数

T max(T a,T b,T c)     //定义一个通用函数,用T作虚拟的类型名

 

l    有默认参数的函数

默认参数值必须从右向左设置,不可间隔参数设置

void f1(float aint b=0int cchar d=a);     //不正确

void f2(float aint cint b=0, char d=a);     //正确

 

l    内部函数和外部函数

extern int fun (int a, int b) //外部函数,可以被其他文件调用。缺省类型。

static int fun(int a,int b) //内部函数,不可被其他文件调用。

 

2.2.2 变量实现

l    局部变量和全局变量

 

l    变量的存储类别

动态存储方式与静态存储方式

 

存储期:变量声明使用销毁的区间,大于作用域。

作用域:变量有效的区间。

 

l    关于变量的声明和定义

auto char c;                   //字符型自动变量,在函数内定义

static int a;                  //静态局部整型变量或静态外部整型变量

register int d;                //整型寄存器变量,在函数内定义

extern int b;                  //声明一个已定义的外部整型变量

 

l    变量属性小结   

一个变量除了数据类型以外,还有3种属性:

(1) 存储类别 C++允许使用auto,static,registerextern 4种存储类别。

(2) 作用域 指程序中可以引用该变量的区域。有局部变量和全局变量

u   局部变量

自动变量,即动态局部变量(离开函数,值就消失)

静态局部变量(离开函数,值仍保留)

寄存器变量(离开函数,值就消失)

形式参数(可以定义为自动变量或寄存器变量)

u   全局变量

静态外部变量(只限本文件引用)

外部变量(即非静态的外部变量,允许其他文件引用)

(3) 存储期 指变量在内存的存储期限。动态存储和静态存储

u   动态存储

自动变量(本函数内有效)

寄存器变量(本函数内有效)

形式参数

u   静态存储

静态局部变量(函数内有效)

静态外部变量(本文件内有效)

外部变量(其他文件可引用)

2.2.3 预处理命令

l    宏定义

#define

l    文件包含

include <系统文件>  //系统目录寻找

include “用户文件” //缺省路径和系统路径寻找,建议使用。

l    条件编译

#ifdef 标识符(#ifndef 标识符)(#if 表达式)

程序段1

#else

程序段2

#endif

2.3 数组

2.3.1 一维和多维数据

l    定义

int a10; a[0],..a[9] // 数组从0下标开始

int a[2][3]; a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2]..

C++中,二维数组中元素排列的顺序是:按行存放,即在内存中先顺序存放第一行的元素,再存放第二行的元素

l    初始化

int a[]={12345}; // 不指定长度

int a5={12345}; // 指定长度,全部赋值

int a5={123}; // 指定长度,不全部赋值

 

int a3][4={{1234}{5678}{9101112}};  

int a3][4={123456789101112};

 

l    关于用数组名作函数参数有两点要说明:

实际参数传递数组地址,具有地址传递特点

(1) 如果函数实参是数组名,形参也应为数组名(或指针变量,关于指针见第5),形参不能声明为普通变量(int array;)。实参数组与形参数组类型应一致(现都为int型),如不一致,结果将出错。

(2) 需要特别说明的是: 数组名代表数组首元素的地址,并不代表数组中的全部元素。因此用数组名作函数实参时,不是把实参数组的值传递给形参,而只是将实参数组首元素的地址传递给形参。

 

2.3.2 字符串数组

l    定义和赋值

char str[]=I am happy;

char str[]={I, ,a,m, ,h,a,p,p,y,′\0};

数组str的长度不是10,而是11(因为字符串常量的最后由系统加上一个′\0)

l    输入输出

char str20;

cin>>str;                  //用字符数组名输入字符串

cout<<str;                 //用字符数组名输出字符串

l    字符串处理函数

strcat(char[],const char[]);

strcpy(char[],const char[]);

strcmp(const char[],const char[]); // 按字符比较Ascii

 

2.3.3 C++处理字符串的方法-字符串类

#include <string>         //注意头文件名不是string.h

string string1=C++;      //定义string1并赋初值

string string2=Language;   //定义string2并赋初值

string1=string1 + string2;   //连接string1string2

cin>> string1;    //从键盘输入一个字符串给字符串变量string1

cout<< string2;   //将字符串string2输出

可以直接用 ==(等于)>(大于)<(小于)!=(不等于)>=(大于或等于)<=(小于或等于)等关系运算符来进行字符串的比较。

 

在字符串变量中存放的是字符串的指针(字符串的地址)4个字节大小。

Sieof(string) 返回的大小一致,都是指针的大小。

 

归纳起来,C++对字符串的处理有两种方法: 一种是用字符数组的方法,这是C语言采取的方法,  一般称为Cstring方法;一种是用string类定义字符串变量,称为string方法。显然,string方法概念清楚,使用方便,最好采用这种方法。C++保留C-string方法主要是为了与C兼容,使以前用C写的程序能用于C++环境。

 

2.4 指针

2.4.1 定义和赋值

float *pointer_3;//定义,变量名称还是pointer_3

pointer_1=&i; //将变量i的地址存放到指针变量pointer_1

pointer_2=&j; //将变量j的地址存放到指针变量pointer_2

// *pointer_1 等于 i

存储

             

(1) 不能用一个整数给一个指针变量赋初值。

(2) 在定义指针变量时必须指定基类型。

 

2.4.2 指针的引用

(1) &取地址运算符。

(2)  *指针运算符(或称间接访问运算符)。

例如: &a为变量a的地址,*p为指针变量p所指向的存储单元。

 

void swap(int *p1,int *p2);     //函数声明

if(a<b) swap(pointer_1,pointer_2);  //函数调用

2.4.3 数组与指针

int a[10];      //定义一个整型数组a,它有10个元素

int *p;        //定义一个基类型为整型的指针变量p

p=&a[0];      //将元素a[0]的地址赋给指针变量p,使p指向a[0]

int *p=a;                //作用与前一行相同

 

如果p的初值为&a[0],则:

(1) p+ia+i就是a[i]的地址,或者说,它们指向a数组的第i个元素

(2) *(p+i)*(a+i)p+ia+i所指向的数组元素,即a[i]

(3) 指向数组元素的指针变量也可以带下标,如p[i]*(p+i)等价。

 

引用数组的方法

(1) 下标法,如a[i]形式;

(2) 指针法,如*(a+i)*(p+i)

 

如果先使p指向数组a的首元素(p=a),则:

(1) p++(或p+=1)。使p指向下一元素,即a[1]。如果用*p,得到下一个元素a[1]的值。

(2) *p++。由于++*同优先级,结合方向为自右而左,因此它等价于*(p++)

(3)*(p++)*(++p)作用不同。前者是先取*p值,然后使p1。后者是先使p1

(4) (*p)++表示p所指向的元素值加1

(5) 如果p当前指向a[i]

*(p--)    先对p进行“*”运算,得到a[i],再使p1p指向a[i-1]

*(++p)   先使p自加1,再作*运算,得到a[i+1]

*(--p)   先使p自减1,再作*运算,得到a[i-1]

 

2.4.4 字符串与指针

1. 用字符数组存放一个字符串

2. 用字符串变量存放字符串

3. 用字符指针指向一个字符串

char *str=I love CHINA!;

2.4.5 函数与指针

int main( )

{int max(int x,int y);              //函数声明

int (*p)(int,int);                 //定义指向函数的指针变量p

int a,b,m;

p=max;                 //使p指向函数max

cin>>a>>b;

m=p(a,b);

cout<<max=<<m<<endl;

return 0;

}

2.4.6 指针数组

int a[10]; //定义一个整型数组a,它有10个元素

int *p;  //定义一个基类型为整型的指针变量p

p=&a[0]; //将元素a[0]的地址赋给指针变量p,使p指向a[0]

p=&a[0];

p=a;

 

1.      p+ia+i就是a[i]的地址

2.      *(p+i)*(a+i)p+ia+i所指向的数组元素a[i]

3.      指向数组元素的指针变量也可以带下标,如p[i]*(p+i)等价

 

(1) 下标法,如a[i]形式,p[i]

(2) 指针法,如*(a+i)*(p+i)

 

2.4.7 指向指针的指针

char **p;       //定义指向字符指针数据的指针变量p

char *name[]={BASIC,FORTRAN,C++,Pascal,COBOL}; // 指针数组;

p=name+2;     //见图6.23p的指向

cout<<*p<<endl;  //输出name[2]指向的字符串

cout<<**p<<endl; //输出name[2]指向的字符串中的第一个字符

 

 

2.4.8 指针小结

数据类型

定义

 

含义

 

int i;

 

定义整型变量

 

int *p;

 

p为指向整型数据的指针变量

 

int a[n];

 

定义整型数组a它有n个元素

 

int *p[n];

 

定义指针数组p它由n个指向整型数据的指针元素组成

 

int (*p)[n];

 

p为指向含n个元素的一维数组的指针变量

 

int f( );

 

f为带回整型函数值的函数

 

int *p( );

 

p为带回一个指针的函数,该指针指向整型数据

 

int (*p)( );

 

p为指向函数的指针,该函数返回一个整型值

 

int **p;

 

p是一个指向指针的指针变量,它指向一个指向整型数据的指针变量

指针运算

NULL = 0

 

有两个与指针变量有关的运算符:

(1) &取地址运算符。

(2)  *指针运算符(或称间接访问运算符)。

例如:

&a为变量a的地址,*p为指针变量p所指向的存储单元

Int a;

Int *pointer;

Pointer = &a;

含义如下:

*&a = *pointer = a

&*pointer = &a

 

2.4.9 引用

主要是实现函数的“地址传递”

 

int  a1a2;

int  &b=a1;

int  &b=a2;    //企图使b又变成a2的引用(别名)是不行的

 

利用引用形参实现两个变量的值互换

void change (int &x,int &y) 

int i=1,j=2 ;

change (i,j);

              

2.5 自定义数据类型

结构体(structure)类型、共用体(union)类型、枚举(enumeration)类型、类(class)类型等这些统称为用户自定义类型(user-defined type,UDT)

2.5.1 structure

struct Student               //声明一个结构体类型Student

{ int num;                 //包括一个整型变量num

char name[20];           //包括一个字符数组name可以容纳20个字符

char sex;                //包括一个字符变量sex

int age;                 //包括一个整型变量age

float score;             //包括一个单精度型变量

char addr[30];           //包括一个字符数组addr,可以容纳30个字符

;                        //最后有一个分号

 

C语言中,结构体的成员只能是数据(如上面例子中所表示的那样)C++对此加以扩充,结构体的成员既可以包括数据(即数据成员),又可以包括函数(即函数成员),以适应面向对象的程序设计。

 

结构成员函数同类成员函数的区别:默认函数属性不同

struct声明的类,如果对其成员不作privatepublic的声明,系统将其默认为public

class定义的类,如果不作privatepublic声明,系统将其成员默认为private

2.5.2 new & delete

分配内存空间

C语言:malloc free

C++ : new ,delete

new 类型(初值)

iInt = new Int(9)

iStruct = new student

 

2.5.3 Union

这种使几个不同的变量共占同一段内存的结构,称为共用体(union)类型的结构(有些书译为联合)

共用体变量所占的内存长度等于最长的成员的长度

不能引用共用体变量,而只能引用共用体变量中的成员

2.5.4 枚举

enum weekday{sunmontuewedthufrisat};

 

2.5.5 typedef声明类型

typedef int INTEGER     //指定用标识符INTEGER代表int类型

typedef float REAL      //指定用REAL代表float类型

 

typedef struct//注意在struct之前用了关键字typedef表示是声明新名

{ int month;

int day;

int year;

DATE //注意DATE是新类型名,而不是结构体变量名

 

3   基于对象的程序设计

3.1 类和对象

3.1.1 面向对象

封装和隐蔽

继承和重用

多态

 

程序 = 对象s + 消息

 

3.1.2 类的声明和对象的定义

(Class)是对象的抽象,而对象是类的具体实例(instance)

类是抽象的,不占用内存,而对象是具体的,占用存储空间

 

3.1.3 成员访问限定符

Public(结构缺省声明的类型)

Private(类缺省声明的类型)

protected声明的成员称为受保护的成员,它不能被类外访问(这点与私有成员类似),但可以被派生类的成员函数访问。

在声明类类型时,声明为private的成员和声明为public的成员的次序任意,既可以先出现private部分,也可以先出现public部分。如果在类体中既不写关键字private,又不写public,就默认为private

 

3.1.4 成员函数的定义

一般成员函数定义在类外部,类函数必须先在类体中作原型声明。

类外定义需要使用全局限定符 ::

1Student:: display( ) 标示类student 的成员函数

2.∷display( ) display( ) 标示全局函数

 

Inline函数

在类体中定义的成员函数中不包括循环等控制结构,C++系统会自动将它们作为内置(inline)函数来处理

 

3.1.5 对象成员的引用

     通过对象名和成员运算符访问对象中的成员;

stud1.num=1001;              

stud1.display( );            

     通过指向对象的指针访问对象中的成员;

同结构的访问类似

class Time

{public:                //数据成员是公用的

int hour;

int minute;

};

Time t,*p;                //定义对象t和指针变量p

p=&t;                     //使p指向对象t

cout<<p->hour;            //输出p指向的对象中的成员hour

p指向t的前提下,p->hour(*p).hourt.hour三者等价。

 

     通过对象的引用变量访问对象中的成员

Time t1;                //定义对象t1

Time &t2=t1;            //定义Time类引用变量t2,并使之初始化为t1

cout<<t2.hour;          //输出对象t1中的成员hour

3.1.6 类声明和成员函数定义的分离

一般在头文件定义类的申明,在CPP文件定义类的实现

//student.h      (这是头文件,在此文件中进行类的声明)

class Student            //类声明       

{ public:           

};

//student.cpp            //在此文件中进行函数的定义

#include <iostream>

#include student.h      //不要漏写此行,否则编译通不过

void Studentdisplay( )  //在类外定义display类函数

{ 

}

 

3.2 关于类和对象的进一步讨论

3.2.1 构造函数

(1) 在类对象进入其作用域时调用构造函数。

(2) 构造函数没有返回值,因此也不需要在定义构造函数时声明类型,这是它和一般函数的一个重要的不同之点。

(3) 构造函数不需用户调用,也不能被用户调用。

(4) 在构造函数的函数体中不仅可以对数据成员赋初值,而且可以包含其他语句。但是一般不提倡在构造函数中加入与初始化无关的内容,以保持程序的清晰。

(5) 如果用户自己没有定义构造函数,则C++系统会自动生成一个构造函数,只是这个构造函数的函数体是空的,也没有参数,不执行初始化操作

 

带参数的构造函数

调用类时必须制定初始化实参

构造函数名(类型 1 形参1,类型2 形参2…)

类名 对象名(实参1,实参2…);

 

用参数初始化表对数据成员初始化

BoxBox(int h,int w,int len)   //在类外定义带参数的构造函数

{height=h;width=w;length=len;}

—》

BoxBox(int h,int w,int len):height(h)width(w)length(len){ }

 

构造函数的重载

实现多个不同的构造函数

 

再次总结沟通函数

(1) 调用构造函数时不必给出实参的构造函数,称为默认构造函数(default constructor)。显然,无参的构造函数属于默认构造函数。一个类只能有一个默认构造函数。

(2) 如果在建立对象时选用的是无参构造函数,应注意正确书写定义对象的语句。

(3) 尽管在一个类中可以包含多个构造函数,但是对于每一个对象来说,建立对象时只执行其中一个构造函数,并非每个构造函数都被执行

 

3.2.2 析构函数

~Student( )                                

当对象的生命期结束时,会自动执行析构函数

析构函数不返回任何值,没有函数类型,也没有函数参数。因此它不能被重载。一个类可以有多个构造函数,但只能有一个析构函数

3.2.3 调用构造函数和析构函数的顺序

调用析构函数的次序正好与调用构造函数的次序相反: 最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用

 

3.3 未完

原创粉丝点击