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

阅读数:285 评论数:0

跳转到新版页面

分类

C/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 <typename T>

通用函数定义


(2)template<class T>

通用函数定义

 

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

 

extern用法

file1.cpp file2.cpp

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

int main() ...

{

cout<<a<<","<<b<<endl;

return 0;

}

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

extern也可用于函数。

 

#include<file>和#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 <iostream>
using namespace std;
int main()
{
void swap(int *,int*);
int i=3,j=5;
swap(&i,&j);
cout<<i<<" "<<j<<endl;
return 0;
}
void swap(int *p1,int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}

 

#include <iostream>
using namespace std;
int main()
{
void swap(int &,int&);
int i=3,j=5;
swap(i,j);
cout<<i<<" "<<j<<endl;
return 0;
}
void swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}


第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 numtype>

class Compare

{...};

使用方法:

Compare<int> cmp;

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

template<class 虚拟类型参数>

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

 


第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);




相关推荐

第1章 认识对象 1.面向对象分析(object-oriented analysis,OOA)的主要任务是分析问题域中的对象、对象之间的关系,然后构造出该问题域的分析模型。分析

有一种特殊的指针叫做成员指针,它们通常指向一个类的成员,而不是对象中成员的特定实例。 <span styl

C++标准每5年会有一个新版本,1998年的C++98、2003年的C++03、2007年的C++TR1、2011年的C++11. 转换操作符 static_ca

组织和策略问题第0条 不要拘泥于小节(了解哪此东本西不应该标准化) 编程规范不应施加个人喜好或者过时的做法。第1条 在高警告级别干净利落地进行编译

它的规则就是当编译器对无限定域的函数调用进行名字查找时,除了当前名字空间域以外,也会把<span style="colo

1、C++版本更迭 <t

1、转换操作 (1)static_cast 将一个值以符合逻辑的方式转型。这个可以看作是&ldquo;利用原值重建一个临时对象,并在设立初值时使用型别转换&rdq

一、概述 GCC一般包括预处理、编译、组装和链接。GCC的运行一般是调用命令gcc,在cross-compiling时使用machine-gcc或machine-gcc-version,在使用c++时

一、概念 所谓的预编译头文件就是把工程中不会经常改变的代码预先编译好放在一个文件里(通过是以.pch为扩展名Precompiled heade

一、string转char* 1、c_str()方法 string str="world"; const char* p = str.c_str();// 加const或等号右边用char* 2、da