《c++程序设计--谭浩强》读书笔记

第一章 C++初步认识

C++对C的“增强”,表现在两个方面:

(1)在原来面向过程的机制基础上,对C语言的功能做了不少扩展

(2)增加了面向对象的机制

 

面向对象和面向过程不是矛盾的,而是各有用途、互为补充,不要把它们对立起来。

 

标准C++要求main函数必须声明为int型。有的操作系统要求执行一个程序后必须向操作系统返回一个值。因此,C++的处理是这样的:如果程序正常运行,则向操作系统返回数值0,否则返回数值-1,在目前使用的一些C++编译系统并未完全执行C++这一规定。

 

C++标准库中的类和函数是在命名空间std中声明的。

 

在C++发展的早期,为了和C语言兼容,许多C++编译系统保留头文件以.h为后缀的用法,如iostream.h,但后来ANSI C++建议头文件不带后缀.h。由于C语言无命名空间,因此用带后缀.h的头文件时也不必用“using namespace std;”作声明。一般main函数也是void类型。

 

编辑-》源程序-》编译-》目标程序-》连接(库文件和其他目标程序)-》可执行程序

 

第二章  数据类型与表达式

C++并没有统一规定各类数据的精度、数值范围、内存中所占用的字节数,因编译系统不同而不同,下面是Visual C++的情况。

类型 字节 范围 写法,[]中的为可选项
short  2   short [int]、unsigned short [int]
int 4   [signed] int, unsigned [int]
long int 4   long [int], unsigned long [int]
char 1   [signed] char, unsigned char
float 4    
double 8    
long double 8    
bool 1    
enum      
数组类型      
struct      
union      
class      
指针类型 4   如果是64,就是8
引用类型      
空类型      

 

数据类型

+基本类型

    +整形                     

        -short

        -int

        -long

    -字符型

    +浮点型

        -float

        -double

        -long double

    -布尔型

+构造类型

    -enum

    -数组类型

    -struct

    -union

    -class

-指针类型

-引用类型

-空类型(void)

 

(1)对于整数类型,C++没有规定每一种数据所占用的字节数,只规定int型数据所占的字节数不大于long型,不小于short型。

(2)整形和字符型前面可以加修饰符signed和unsigned,如果指定为signed,则数值以补码形式存放。

 

整数常量有不同的表示方式:

(1)后面加一个字母l或L,表示long int。这往往用于函数调用中,如果函数的形参为long int,则要求实参也为long int,此时用123作实参不行,而要用123L作实参。

(2)在常数的开头加一个数字0,就表示 是以八进制形式表示的常数

(3)在常数的开头加一个数字0和一个字母X(或x),就表示以十六进制的常数

 

浮点数常量的不同表示方式:

(1)十进行小数形式。由整数部分和小数部分组成,可以省略其一(如78.,.06,.0),但不能二者皆省略。一般按double类型处理,如果数字后有F或f,表示按float处理,如果后有L或l,则按long double处理。

(2)指数形式。如3.14e0,e前一定要有数字。按double处理。

 

‘a'的ASCII码是97,而‘A'的ASCII码是65.每个小写字母比它相应的大写字母大32。

 

编译系统会在字符串最后加上一个’\0'作为字符串结束标志,但‘\0’并不是字符串的一部分。

 

如果在一个字符串中最后一个字符为“\”,则表示它是一个续行符,下一行的字符是该字符串的一部分,且在两行字符串间无空格。如:

cout<<"We must study c\
++ hard!";


C++规定标识符只能由字母、数字、下划线组成,且第一个字符为字母或下划线。

 

区别const与#define

#define的符号常量只是用一个符号代替一个字符串,在预编译时把所有符号常量替换为所指定的字符串,它没有类型,在内存中并不存以符号常量命名的存储单元。而const常变量具有变量的特征,它具有类型,在内存中存在着以它命名的存储单元,可以用sizeof运算符测出其长度。与一般变量的不同是其值不能改变。虽然二者的实现方法不同,但从使用的角度看,都可以认为用了一个标识符代表了一个常量。

 

运算符与结合性
优先级 运算符 含义 结合方向
1 :: 域运算符 自左向右
2 ()
[ ]
->
.
++
--
括号,函数调用 
数组下标运算符
指向成员运算符
成员运算符
自增运算符(后置)
自减运算符(后置)
自左向右
3 ++
--
~
!
-
+
*
&
(类型)
sizeof
new
delete
自增运算符(前置)
自减运算符(前置)
按位取反运算符
逻辑非运算符
负号运算符
正号运算符
指针运算符
取地址运算符
类型转换运算符
长度运算符
动态分配空间运算符
释放空间运算符
自右向左,
单目运算符
4 *
/
%
乘法运算符
除法运算符
求余运算符
自左向右
       
5 +
-
加法运算符
减法运算符
自左向右
6 <<
>>
按位左移运算符
按位右移运算符
自左向右
7 < <= > >= 关系运算符 自左向右
8 ==
!=
等于运算符
不等于运算符
自左向右
9 & 按位与运算符 自左向右
10 ^ 按位异或运算符 自左向右
11 | 按位或运算符 自左向右
12 && 逻辑与运算符 自左向右
13 || 逻辑或运算符 自左向右
14 ?: 条件运算符 自右向左
15 = += -= *= /= %=
>>= <<= &= ^= !=
赋值运算符 自右向左
16 throw 抛出异常运算符 自右向左
17 , 逗号运算符 自左向右

记忆顺口溜:醋坛酸味罐,味落跳福豆。

初等-》单目-》算术-》位移-》关系,按位运算-》逻辑-》条件-》赋值-》逗号

 

运算中类型的自动转换

double<----float

^

|

long

^

|

unsigned

^

|

int<----char,short

(1)横向向左的箭头表示必定的转换,即使是两个float型数据相加,也先都转换成double型

(2)纵向箭头表示不同类型时转换的方向

 

强制类型转换有两种方式:

(1)(类型名)(表达式),源于C语言

(2)类型名(表达式),提倡

 

a=(b=5)赋值表达式作为右值,等价于a=b=5,因为“=”结合性自右向左。

(a=3*5)=4*3赋值表达式作为左值,此时括号不能去掉

 

表达式1,表达式2

先求解表达式1,再求解表达式2,整个逗号表达式的值是表达式2的值。

例如:a=3*5,a*4  

结果为60

 

第三章  程序设计初步

在C语言中,只有产生实际操作的才称为语句,对变量的定义不作为语句,而且要求对变量的定义必须出现在本块中所有程序语句之前,在C++中,对变量的定义被认为是一条语句,并且可以出现在函数中的作何行。

 

输入输出流的控制符
控制符 作用
dec 设置数值的基数为10
hex 设置数值 的基数为16
oct 设置数值 的基数为8
setfill(c) 设置填充字符c,c可以是字符常量或字符变量
setprecision(n) 设置浮点数的精度为n位。在以一般十进制小数形式输出时,n代表有效数字。
在以fixed(固定小数位数)形式和scientific(指数)形式时,n为小数位数
setw(n) 设置字段宽度为n
setiosflags(ios::fixed) 设置浮点数以固定小数位数显示
setiosflags(ios::scientific) 设置浮点数以指数形式显示
setiosflags(ios::left) 输出数据左对齐
setiosflags(ios::right) 输出 数据右对齐
setiosflags(ios::skipws) 忽略前导空格
setiosflags(ios::upppercase) 数据以十六进制输出时,字母以大写表示
setiosflags(ios::lowercase) 数据以十六进制输出时,字母以小写表示
setiosflags(ios::showpos) 输出正数时,给出“+”号

需加引用iomanip头文件 ,这些设置对其后的输出均有效,而setw只对其中一个输出项有效。

 

第四章  函数和预处理

在C语言中规定:如果定义函数时不指定函数类型,系统会隐含指定函数为int型,因此int max(int x,int y)可以简写为max(int x,int y),但C++取消了这一规定。

在编译时将所调用函数的代码直接嵌入到主调函数中,而不是将流程转出去,这种嵌入主调函数中的函数称为内置函数,又称为内嵌函数或内联函数。语法上只需要在函数左端加一个关键字inline即可,可以在声明函数和定义函数处任何一处,但这对于编译系统而言只是建议性的。

 

函数模板的一般形式:

(1)template

           通用函数定义


(2)template

         通用函数定义

 

实参与形参的结合是从左至右顺序进行的,因此指定默认值的参数必须放在形参表列中的最右端。另外如果函数的定义在函数调用之前,则应在函数定义中给出默认值。否则需要在函数声明中给出默认值 。

 

extern用法

file1.cpp                                                            file2.cpp

extern int a,b;                                                    int a=3,b=4;

int main()                                                            ...

{

cout<

return 0;

}

但是如果file2.cpp中变为static int a=3,b=4,那么file1.cpp就不能引用了,因为static修饰后作用域只能限于本文件。

extern也可用于函数。

 

#include和#include"file"区别

用尖括号时,系统到系统目录中寻找要包含的文件,如果找不到,编译系统就会给出错误信息。所谓系统目录是指存放C++系统的目录,而双引号形式,默认从用户当前目录找,也可以在双此号中给出路径,如果找不到再到系统目录找。

 

 

条件编译:

(1)

#ifdef 标识符

程序段1

#else

程序段2

#endif

(2)

#if 表达式

程序段1

#else

程序段2

#endif

 

第五章 数组

void select_sort(int array[10],int n)

void select_sort(int array[],int n)

void select_sort(int array[5],int n)

三者是等价的,因为array[]中方括号内的数值并无实际作用,编译系统对一维数组方括号内的内容不予处理。对于二维数组

void fun(int array[10][3])

void fun(int array[][3])

void fun(int array[5][3])

三者是等价的,第二维不可省,因为数组在内存中是按行存储。

 

字符串处理函数

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

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

(3)strcmp(const char[],const char[]);

(4)strlen(const char[]);

 

第六章  指针

*(p++)与*(++p)

前者是先取*p值,然后使p加1 。后者是先使p加1,再取*p。

 

*(a[i]+j),  *(*(a+i)+j)与a[i][j]等价

 

int (*p)[4]与int *p[4]的区别

前者表示p是一个指针变量,它指向包含4个整形元素的一维数组。后者是一个指针数组。

 

#include 
using namespace std;
int main()
{
void swap(int *,int*);
int i=3,j=5;
swap(&i,&j);
cout<

 

#include 
using namespace std;
int main()
{
void swap(int &,int&);
int i=3,j=5;
swap(i,j);
cout<

 

第7章 自定义数据类型

结构体的成员既可以包括数据,又可以包括函数。在C语言中,在定义结构体变量时,要在结构类型名前加上关键字struct,如

struct Student stu;

C++保留了这种方式,但也可以不添加

Student stu2;

也下面两种定义struct变量的方式:

(1)struct 结构体名

{

成员列表

}变量名表列;

(2)

struct

{

成员列表

}变量名表列;

 

结构体变量.成员名

(*p)。成员名

p->成员名

三者等价

 

 

共用体

union 共用体类型名

{

成员表列;

};

结构体变量所占内存长度是各成员的内存长度之和,共用体变量所占内存长度等于最长的成员的长度。

(1)在每个瞬时,只能存入其中一种,而不是同时存放几种

(2)不能在定义共用体变量时对它初始化,不能用共用体变量作为函数参数

 

 

枚举

enum 枚举类型名 {枚举常量表列;}

 

在c语言中,定义枚举变量要包括enum关键字。如:enum weekday workday;

而在c++中,保留了这种写法,但也可以不使用enum关键字。如:weekday workday;

(1)枚举元素作为常量,它们是有值的,按定义时的顺序对它们赋值为0,1,2……

(2)也可以在声明枚举类型时另行指定枚举元素的值

如:

enum weekday {sum=7,mon=1,tue,wed,thu,fri,sat};

这样从mon=1,以后按顺序加1 ,sat为6

 

还可以使用typedef声明一个新的类型来代替已有的类型。

如:

typedef struct {

int month;

int day;

int year;

}DATE;

这样,DATE就是新类型名。

 

第八章  类和对象

第九章  关于类和对象的进一上讨论

类的数据成员是不能在声明类时初始化,应该在cpp内初始化。

 

 

参数初始化列表:

这种方法不在函数体内对数据成员初始化,而是在函数首部。如
Box::Box(int h,int w):height(h),width(w){}

 

默认参数的构造函数:

(1)应该在声明构造函数时指定默认值,而不能只在定义构造函数时指定默认值。

(2)声明构造函数时,形参名可以省略。如:

Box(int=10,int=10,int=10);

 

常对象:

常对象必须要有初值,其所有的成员的值都不能被修改。它有两种定义形式:

(1)类名 const 对象名 [(实参表列)]

(2)const 类名 对象名 [(实参表列)]

常对象不能调用非const型的成员函数(除了由系统调用的构造函数和析构函数)。

 

常成员函数:

如:get_time() const;

const是函数类型的一部分,在声明函数和定义函数时都要有const关键字,它不能修改数据成员,但是声明为mutable的数据成员还是可以修改的,如:

mutable int count;

 

常数据成员:

是用关键字const来声明的数据成员,它只能通过构造函数的参数初始化列表对常数据成员进行初始化。

 

数据成员 非const成员函数 const成员函数
非const的数据成员 可以引用,也可以修改 可以引用,但不可以修改
const的数据成员 可以引用,不可以修改 可以引用,不可以修改
const对象的数据成员 不允许 可以引用,不可以修改


常指针:

类名  * const  指针变量名;

这样指针值始终保持为其初值,不能改变。但是可以改变其所指向对象的值。

 

指向常变量的指针:

const 类型名 * 指针变量名;

(1)如果一个变量已被声明为常变量,只能用指向常变量的指针变量指向它。

(2)当指向非const变量时,不能通过指针改变该变量的值。

 

静态数据成员:

(1)在所有对象之外单独开辟空间

(2)只能在类体外进行初始化,同时不能用参数列表进行初始化。

数据类型  类名::静态数据成员名=初值;

不必在初始化语句中加入static。

 

 

静态成员函数:

与静态数据成员不同,静态成员函数的作用不是为了对象之间的沟通,而是为了能处理静态数据成员。

(1)没有this指针

(2)可以直接引用本类的静态数据成员

 

友元:

friend关键字可以使其访问类的私用函数。友元关系不能传递,即如果B类是A类的友元,C是B类的友元,不代表C是A的友元。

 

类的提前声明:

类的声明的使用范围是有限的,只有在正式字义了一个类以后,才能用它定义类对象。

 

模板:

模板类,如:

template

class Compare

{...};

使用方法:

Compare cmp;

如果在类模板外定义成员函数,应写成类模板形式:

template

函数类型 类模板名 <虚拟类型参数> ::成员函数名(函数形参表列) {...}

 

 

第10章  运算符重载

f运算符重载实质上是函数的重载。一般格式如下:

函数类型  operator 运算符名称  (形参列表)

{对运算符的重载处理}

(1)c++不允许用户自定义新的运算符,只能对已有的C++运算符进行重载。

(2)有5种运算符不能重载:成员访问运算符(.)、成员指针访问运算符(.*)、域运算符(::)、长度运算符(sizeof)、条件运算符(?:)

(3)不能改变操作数的个数

(4)不能改变运算符优先级

(5)不能改变运算符的结合性

(6)不能有默认的参数

(7)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个类对象(类对象引用)

 

C++约定,在自增(自减)运算符重载函数中,增加一个int形参,就是后置自增(自减)运算符。如

Time operator ++();//前置++

Time operator ++(int);//后置++

 

istream &operator >>(istream &,自定义类型 &);

ostream &operator <<(ostream &,自定义类型 &);

 

 

转换构造函数的作用是将一个其他类型转换成一个类的对象。

类型转换函数的作用是将一个类的对象转换成另一个类型的数据。

类型转换函数的一般形式:

operator 类型名()

{实现转换的语句}

 

第11章  继承与派生

虚基类:

C++提供虚基类的方法,使得在继承间接共同基类时只保留一份成员。虚基类并不是在声明基类时声明,而是在申明派生类时,指定继承方式时声明的。如:

class 派生类:virtual 继承方式 基类名

在最后的派生类中不仅要负责对其直接基类进行初始化,还要负责对虚基类的初始化。

 

第12章  多态性与虚函数

虚函数的使用方法

(1)在基类中用virtual声明成员函数为虚函数。这样就可以在派生类中重新字义此函数,为它赋予新的功能,并能方便地被调用。在类外定义虚函数时,不必再加virual。

(2)当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。因此在派生类重新声明该函数时,可以加virtual,也可以不加,但习惯上一般在每一层声明该函数时都加virtual,使程序更加清晰。

(3)通过虚函数与指向基类对象的指针以实现多态性。

(4)有时在基类中定义的非虚函数会在派生类中被重新定义,如果用基类指针调用该成员函数,则系统会调用对象中基类部分的成员函数,这显然不是多态性。同一类族的虚函数的首部是相同的,而函数重载时函数的首部是不同的(参数个数或类型不同)

 

如果将基类的析构函数函数声明为虚构函数时,由该基类所派生的所有派生类的析构函数也都自动成为虚函数。

 

声明纯虚函数的一般形式:

virtual 函数类型 函数名(参数列表)=0;

(1)纯虚函数没有函数体(2)最后的=0;只是告诉编译系统“这是纯虚函数”(3)这是声明语句,最后应用分号。

凡是包含纯虚函数的类都是抽象类,如果在派生类中没有对所有的纯虚函数进行定义,则此派生类仍然是抽象类,不能用来定义对象,但是可以定义指向抽象类的指针。

 

第13章 输入输出流

常用的头文件:

  • iostream 包含了对输入输出流进行操作所需的基本信息
  • fstream   用于用户管理的文件的IO操作
  • strstream 用于字符串流IO
  • stdiostream 用于混合使用C和C++的IO机制时,例如想将C程序转变为C++程序
  • iomanip 在使用格式化IO时应包含此头文件
流成员函数 与之作用相同的控制符 作用
precision(n) setprecision(n) 设置实数的精度为n位
width(n) setw(n) 设置字段宽度为n
fill(c) setfill(c) 设置填充字符c
setf() setiosflags() 设置输出格式状态,括号中应给出格式状态,内容与控制符setiosflags括号中的内容相同
unsetf() resetioflags 终止已设置的输出格式状态

 

流成员函数put

专用于输出单个字符的成员函数。还可以使用putchar,它是C语言中使用的,C++保留了这个函数。

 

流成员函数get

用于字符的输入,有3个形式

(1)cin.get()

若遇到输入流中的文件结束符,则函数返回文件结束标志EOF(End Of File)

(2)cin.get(ch)

从输入流中读取一个字符,赋值给字符变量ch,如果读取成功则函数返回非0值。

(3)cin.get(字符数组,字符个数n,终止字符)

从输入流中读取n-1个字符,赋给指定的字符数组,如果在读取n-1字符之前遇到指定的终止字符,则提前结束读取。

 

流成员函数getline

用于读到一行字符

cin.getline(字符数组,字符个数n,终止标志字符);

 

流成员函数eof

表示“文件结束”,从输入流读取数据,如果到达文件末尾(遇到文件结束符),返回非零值。

 

流成员函数peek

观察下一个字符,cin.peek函数返回当前字符,但指针仍停留在当前位置

 

流成员函数putback

cin.putback(ch);

将前面用get或getline函数从输入流中读取的字符ch返回到输入流,插入到当胶指针位置,以供后面读取。

 

流成员函数ignore

cin.ignore(n,终止字符)

跳过输入流中n个字符,或在遇到指定的终止字符时提前结束(此进跳过包括终止字符在内的若干字符)

 

文件流对象.open(磁盘文件名,输入输出方式);

磁盘文件名可以包括路径,如果缺省路径,则默认为当前目录下的文件。

 

与文件指针相关的流成员函数 作用
gcount 返回最后一次输入所读入的字节数  
tellg 返回输入文件指针的当前位置   
seekg(文件中的位置) 将输入文件中指针移到指定的位置  
seekg(位移量,参照位置) 以参照位置为基础移动若干个字节  
tellp 返回输出文件指针当前的位置  
seekp(文件中的位置 ) 将输出文件中的指针移到指定的位置   
seekp(位移量,参照位置) 以参照位置为基础移动若干个字节  

参照位置可以为:

ios::beg  文件开关,这是默认值

ios::cur  指针当前的位置

ios::end  文件末尾

 

内存流

ostrstream::ostrstream(char *buffer,int n,int mode=ios::out);

buffer是指向字符串数组首元素的指针,n为指定的流缓存区的大小

istrstream::istrstream(char *buffer);

istrstream::istrstream(char* buffer,int n);

 

最后欢迎大家访问我的个人网站: 1024s

你可能感兴趣的:(c++/c)