《C面向对象程序设计》谭浩强版复习总结

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第一章C++ 基础
endl 换行并刷新输出流
setw(n) 设置字段位数为n
hex,oct,dec 十六进制,八进制,十进制表示
setfill 定义填充字符
setprecision 定义浮点数的精度
left,right 左对齐,右对齐
showpoint 强制显示小数点以及全部尾部0
C++通过给常量命名的方式定义常量:
const<数据类型名><常量名>=<表达式>
用const定义的标识符常量时,一定要对其初始化。

在说明时进行初始化是对这种常量置值的唯一方法,不能用赋值运算符对这种常量进行赋值。

函数声明的一般形式为
函数类型函数名(参数表)
函数模板的定义
template<typename 或class T>
函数定义
例子:template<typename T>
T max(T a,T b){
return(a>b)? a:b;
}
定义函数模板时可以使用多个类型参数,每个类型参数前面只需加上关键字typename或class,用逗号分隔:
template <class T1, class T2, class T3>
例子:template<class T1, class T2>
T1 max(T1 a,T2 b){
return (a>b) ? a : (T1)b;
}
有默认参数的函数:实参与形参的结合是从左至右进行的,因此指定默认值的参数必须放在形参列表中的最右端
引用
定义对变量起另外一个名字(别名alias),这个名字称为该变量的引用。

<类型> &<引用变量名> = <原变量名>;
其中原变量名必须是一个已定义过的变量。

如:
int max ;
int &refmax=max;
refmax并没有重新在内存中开辟单元,只是引用max的单元。

max与refmax在内存中占用同一地址,即同一地址两个名字。

对引用类型的变量,说明以下几点:
1、引用在定义的时候要初始化
2、对引用的操作就是对被引用的变量的操作。

3、引用类型变量的初始化值不能是一个常数。

4、一旦引用被声明,它就不能再指向其它的变量。

5、对引用的初始化,可以用一个变量名,也可以用另一个引用。

6、引用同变量一样有地址,可以对其地址进行操作,即将其地址赋给一指针。

当&m的前面有类型符时(如int &m),它必然是对引用的声明;如果前面无类型符(如cout<<&m),则是取变量的地址。

7、对常量(用const声明)的引用使用如下方式:
int i=5;
const int &a=i;
内联函数定义的一般格式为:
inline <函数值类型> <函数名>(<参数表>)
{
<函数体>
}
作用域运算符
::a表示全局作用域中的变量a。

注意:不能用::访问函数中的局部变量
new运算从堆中分配一块与<类型>相适应的大小为<元素个数>的数组存储空间,若分配成功,将这块存储空间的起始地址存入<指针变量名>,否则置<指针变量名>的值为NULL(空指针值,即0)。

new的使用格式为:
<指针变量名>=new <类型>[<元素个数>];
delete运算符用来释放<指针变量名>指向的动态存储空间。

使用格式如下:delete <指针变量名> 或
delete[] <指针变量名>
第2章面向对象基本概念
面向过程编程与面向对象编程的区别:
面向过程编程先确定算法,再确定数据结构;
面向对象编程先确定数据结构,再确定运算。

类定义:
class <类名>
{
<访问控制符>:
<成员函数的声明>
<访问控制符>:
<数据成员的声明>
};
<成员函数的实现>
若在类体外实现,则需要使用作用域运算符“::”,用它来标识某个成员函数是属于哪个类的,其定义格式如下:
<函数值类型> <类名>::<成员函数名>(<参数表>)
{
<函数体>
}
类外访问对象中的成员可以有3种方法:
通过对象名和成员运算符访问对象中的成员。

<对象名>.<公有成员>
通过指向对象的指针变量访问对象中的成员。

<对象指针名> -> <公有成员>
通过对象的引用访问对象中的成员。

析构函数其定义格式如下:
<类名>::~<类名>()
{
<函数体>
}
在一般情况下,调用构造函数与声明对象的顺序相同,而调用析构函数的次序正好与创建对象的顺序相反。

三种构造函数
Box(); //无参构造函数
Box(int h,int w ,int len)
:height(h),width(w),length(len){}
//带参构造函数
复制构造函数定义
<类名>(<参数表>);
<类名>(const <类名>& <对象名>)
Box(const Box& b);//复制构造函数
复制构造函数只有一个参数,并且是对同类对象的引用。

静态成员是类的所有对象共享的成员,而不是某个对象的成员,它在对象中不占存储空间,是属于整个类的成员。

静态成员定义格式如下:
static<静态成员的定义>;
不能用参数初始化表对静态数据成员初始化,也不能在构造函数体内初始化,静态数据成员只能在类体外进行初始化。

静态数据成员初始化格式如下:
<数据类型> <类名>::<静态数据成员名>=<值>;
在类的成员函数中可以直接访问该类的静态数据成员,而不必使用成员访问运算符或类名限定修饰符。

在类外必须使用成员访问运算符或类名限定修饰符访问公共静态数据成员。

<对象名>.<静态成员>
<类名>::<静态成员>
静态成员函数就是使用static关键字声明的成员函数。

静态成员函数可以直接访问该类的静态成员,但不能直接访问类中的非静态成员。

第3章详解对象
对象指针就是用于存放对象数据起始地址的变量。

声明对象指针的一般格式为:
<类名> *<对象指针名>;
对象指针的初始化一般格式为:
<数据类型> *<对象指针名>=&<对象名>;
<对象指针名>=&<对象名>;
通过指针访问对象成员一般格式如下:
<对象指针名> -> <公有成员>
boxp->volumn();
(*<对象指针名>).<公有成员>
(*boxp).volumn();
this指针是一个特殊的隐含指针,它隐含于每一个成员函数(静态成员函数除外)中,也就是说,每个成员函数都有一个this指针参数。

this指针指向调用该函数的对象,即this指针的值是当前被调用的成员函数所在的对象的起始地址。

复制构造函数中隐含使用this指针:
TAdd(const TAdd& p)
{
this->x=p.x; this->y=p.y;
cout<<"copy constructor."<<endl;
}
同样也可以使用*this来标识调用该成员函数的当前对象。

x this->x (*this).x
this指针是一个const指针,成员函数不能对其进行赋值。

静态成员中不能访问this指针,因为静态成员函数不从属于任何对象。

指向非静态数据成员的指针一般形式为:
数据类型名*指针变量名;
定义指向公有成员函数的指针变量的一般形式为:
数据类型名(类名:: *指针变量名)(参数列表);
使指针变量指向一个公有成员函数的一般形式为:
指针变量名=&类名::成员函数名
常量定义格式如下:
const <数据类型名> <常量名>=<表达式>;
常对象是其数据成员值在对象的整个生存期间内不能被改变的对象。

const <类名><对象名>(<初始化值>);
<类名> const <对象名>(<初始化值>);
常成员函数
通过常成员函数来引用本类中的常数据成员。

<数据类型><函数名>(<参数表>)const;
声明一维对象数组的一般格式为:<类名> <数组名>[<下标表达式>]
第4章运算符重载
重载为类的成员函数格式如下:
<类名> operator <运算符>(<参数表>)
{ 函数体}
A operator + (A &);
++为前置运算符时,它的运算符重载函数的一般格式为:
<type> operator ++( )
++为后置运算符时,它的运算符重载函数的一般格式为:
<type> operator ++(int)
运算符重载函数不能定义为静态的成员函数,因为静态的成员函数中没有this 指针。

友元声明以关键字friend开始,只能出现在被访问类的定义中。

具体格式如下:
friend <函数值类型> <函数名>(<参数表>);
friend class <类名>;
友元函数可以访问该类中的所有成员(公有的、私有的和保护的)
通常使用友元函数来取对象中的数据成员值,而不修改对象中的成员值,保证数据安全。

重载为类的友元函数语法形式
friend <函数值类型> operator <运算符>(<参数表>)
{ <函数体>;}
++为前置运算符时,它的运算符重载函数的一般格式为:A operator ++(A &a)
++为后置运算符时,它的运算符重载函数的一般格式为:A operator ++(A &a, int)
重载提取运算符的一般格式为:
friend istream & operater >>(istream &, ClassName &); istream & operater >>(istream &is, ClassName &f){…}
重载输出(插入)运算符的一般格式为:
friend ostream & operater >>(ostream &, ClassName &); ostream & operater >>(ostream &is, ClassName &f){…} 重载类型转换运算符函数格式:
operator〈返回基本类型名〉()
{
……
return 〈基本类型值〉
}
类类型转换函数只能是成员函数,不能是友元函数。

转换函数的操作数是对象。

第5章继承与派生
派生是指由基类创建新类的过程。

class A
{ int i; //基类成员};
class B:public A //A派生了B,B继承了A,
//B自动拥有A的成员
{ int j; //定义派生类的新成员};
派生类的定义格式如下:
class <派生类名>:<继承方式> <基类名>
{ <派生类新定义成员> };
派生类继承了基类的全部数据成员和除了构造、析构函数之外的全部成员函数,它们在派生类中的访问属性由继承方式控制。

三种继承方式下派生类中基类成员的访问控制权限
无论是哪种继承方式,基类的私有成员在派生类中都是不可被访问的。

只能通过基类的成员函数访问基类的私有数据成员。

解决的办法是通过成员初始化表来完成,在成员初始化表中可以显式调用基类构
造函数。

<派生类名>(<总参数表>):<基类名>(<参数表1>),<对象成员名>(<参数表2>)
{
<派生类数据成员的初始化>
};
构造函数调用顺序为:基类的构造函数→对象成员构造函数→派生类的构造函数。

析构函数调用顺序刚好相反。

当基类中没有显式定义构造函数,或定义了无参构造函数时,派生类构造函数的初始化表可以省略对基类构造函数的调用,而采用隐含调用。

当基类的构造函数使用一个或多个参数时,派生类必须定义构造函数,提供将参数传递给基类构造函数的途径。

这时,派生类构造函数的函数体可能为空,仅起到参数传递作用。

如果在基类中既定义了无参构造函数,又定义了带参构造函数,则在定义派生类构造函数时,既可以包含基类构造函数和参数,也可以不包含基类构造函数。

如果在一个派生类中要访问基类中的私有成员,可以将这个派生类声明为基类的友元。

友元关系是不能继承的。

B类是A类的友元,C类是B类的派生类,则C类和A 类之间没有任何友元关系,除非C类声明A类是友元。

多继承派生类的定义
class <派生类名>:<继承方式> <基类名1>,…,<继承方式> <基类名n>
{ <派生类新定义成员> };
多继承派生类的构造函数
<派生类名>(<总参数表>):<基类名1>(<参数表1>),…,< 基类名n> (<参数表n>) {
<派生类数据成员的初始化>
};
<总参数表>必须包含完成所有基类初始化所需的参数
构造函数调用顺序是:先调用所有基类的构造函数,再调用对象成员类构造函数,最后调用派生类的构造函数。

处于同一层次的各基类构造函数的调用顺序取决于定义派生类时所指定的基类顺序,与派生类构造函数中所定义的成员初始化列表顺序无关。

如果有多个成员类对象,则构造函数的调用顺序是对象在类中被声明的顺序,而不是它们出现在成员初始化表中的顺序。

析构函数的调用顺序与构造函数的调用顺序相反。

虚基类
虚基类的定义格式为:
class <派生类名>:virtual <继承方式><共同基类名>;
【说明】引进虚基类后,派生类对象中只存在一个虚基类成员的副本。

虚基类的初始化与一般多继承的初始化在语法上相同,但构造函数的调用顺序有所不同,规则如下:
先调用虚基类的构造函数,再调用非虚基类的构造函数。

若同一层次中包含多个虚基类,其调用顺序为定义时的顺序。

若虚基类由非虚基类派生而来,则仍按先调用基类构造函数,再调用派生类构造函数的顺序。

如果在虚基类中定义了带参数的构造函数,则要在其所有派生类(包括直接派生类或间接派生类)中,通过构造函数的初始化表对虚基类进行初始化。

第6章多态性与虚函数
类型兼容规则
类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代。

类型兼容规则中所指的替代包括以下情况:
派生类的对象可以赋值给基类的对象。

派生类的对象可以初始化基类的引用。

派生类的对象的地址可以赋值给基类的指针变量。

在替代之后,派生类对象就可以作为基类的对象使用,但只能访问从基类继承的成员。

只能用派生类对象对其基类对象赋值,而不能用基类对象对其派生类对象赋值。

同一基类的不同派生类对象之间也不能赋值。

虚函数
虚函数就是在基类中被关键字virtual说明、并在一个或多个派生类中被重新定义的成员函数。

声明虚函数的格式如下:
virtual <函数值类型> <函数名>(<参数表>);
在派生类中重新定义虚函数时,其函数原型包括返回类型、函数名、参数个数、类型和顺序,都必须与基类中的原型相同。

一个函数一旦被声明为虚函数,则无论声明它的类被继承了多少层,在每一层派生类中该函数都保持虚函数特性。

因此,在派生类中重新定义该函数时,可以省略关键字virtual。

实现动态的多态性时,必须使用基类类型的指针变量或对象引用,并使其指向不同的派生类对象,并通过调用指针或引用所指向的虚函数才能实现动态的多态性。

可将类簇中具有共性的成员函数声明为虚函数,而具有个性的函数没有必要声明为虚函数。

但是下面的情况例外:
静态成员函数不能声明为虚函数。

构造函数不能是虚函数。

内联成员函数不能声明为虚函数。

析构函数可以是虚函数。

虚析构函数
虚析构函数的声明格式如下:
virtual ~<类名>();
如果一个类的析构函数是虚函数,那么,由它派生的所有子类的析构函数也是虚函数。

纯虚函数用virtual声明,没有任何实现、必须由派生类覆盖该函数提供实现
纯虚函数的声明格式为:
virtual <函数值类型> <函数名>(<参数表>)=0;
包含一个或多个纯虚函数的类称为抽象类。

如果派生类没有实现基类中的所有纯虚函数,派生类也是抽象类。

抽象类无法实例化,即不能创建抽象类的对象。

第7章输入输出
iostream:I/O流类库的最主要的头文件,包含了对输入输出流进行操作所需的基本信息,还包括cin、cout、cerr和clog共4个流对象。

fstream:用于用户管理的文件的I/O操作。

strstream:用于字符串流I/O。

stdiostream:用于混合使用C和C++的I/O操作。

iomanip:使用格式化I/O时应包含此头文件。

用setf函数设置状态标志,其一般格式如下:
long ios::setf(long flags)
清除状态标志
用unsetf函数清除状态标志,其一般格式如下:
long ios::unsetf(long flags)
用函数flags取状态标志有两种形式,其格式分别如下:
long ios::flags()
//返回与流相关的当前状态标志值
long ios::flags(long flag)
//将流的状态标志值设置为flag,并返回设置前的状态标志值。

以上三组函数必须用流类对象(cin或cout)来调用,其格式如下:
<流对象名>.<函数名>(ios::<状态标志>)
cout.setf(ios::showpos);
cout.setf(ios::scientific);
cout.setf(ios::showpos| ios::scientific);
设置输出宽度函数有两种形式,其格式分别如下:
int ios::width(int len)
int ios::width()
第一种形式是设置输出宽度,并返回原来的输出宽度;
第二种形式是返回当前输出宽度,默认输出宽度为0。

只对其后的第一个输出项有效。

填充字符的作用是当输出值不满输出宽度时用填充字符来填充,默认填充字符为空格。

它与width()函数配合使用,否则没有意义。

设置填充字符函数有两种形式,其格式分别如下:
char ios::fill(char ch)
char ios::fill()
第一种形式是重新设置填充字符,并返回设置前的填充字符;
第二种形式是返回当前的填充字符。

设置浮点数输出精度有两种形式,其格式分别如下:
int ios::precision(int p)
int ios::precision()
第一种形式是重新设置输出精度,并返回设置前的输出精度;
第二种形式是返回当前的输出精度。

默认输出精度为6
用get函数读入一个字符
(1)不带参数的get函数
cin.get()用来从指定的输入流中提取一个字符(包括空白字符),函数的返回值就是读入的字符。

若遇到输入流中的文件结束符,则函数返回文件结束标志EOF。

(2)有一个参数的get函数
cin.get(ch)用来从输入流中读取一个字符,赋给字符变量ch。

读取成功返回非0值(真),如失败(遇文件结束符)则函数返回0值(假)。

3)有三个参数的get函数
cin.get(字符数组/字符指针,字符个数n,终止字符)
从输入流中读取n-1个字符,赋给指定的字符数组(或字符指针指向的数组)。

如果在读取n-1个字符之前遇到指定的终止字符,则提前读取结束。

如果读取成功返回非0值(真),如失败(遇文件结束符)则函数返回0值(假)。

用getline函数读入一行字符
cin.getline(字符数组(或字符指针),字符个数n,终止字符)
从输入流中读取一行字符,其用法与带3个参数的get函数类似。

eof函数
无参函数,表示文件结束。

从输入流读取数据,如果到达文件末尾(遇文件结束符),返回非零值(真),否则为0(假)。

while(!cin.eof())
peek函数
无参函数,表示“观察”,观测下一个字符。

返回值是当前指针指向的当前字符,但只是观测,指针仍停留在当前位置,并不后移。

如果要访问的字符是文件结束符,则函数值是EOF。

c=cin.peek();
putback函数
将前面用get或getline函数从输入流中读取的字符ch返回到输入流,插入到当前指针位置,以供后面读取。

控制符不属于任何类成员,定义在iomanip头文件中
设置输入/输出宽度setw(int)
用整型参数来制定输入/输出域的宽度。

使用时只对其后一项输入/输出有效。

当用于输出时,若实际宽度小于设置宽度时,数据向右对齐,反之则按数据的实际宽度输出。

当用于输入时,若输入的数据宽度超过设置宽度时,超出的数据部分被截断而被作为下一项输入内容。

设置输出填充字符setfill(char)
与ios::fill相同,常与setw(int)联合使用,从而向不满设置输出宽度的空间填入指定的字符,不设置则填空格。

设置后直至下一次设置前一直有效。

参数可以是字符常量或字符变量。

设置输出精度setprecision(int)
指明输出实数的有效位数。

参数为0时,按默认有效位数6输出。

在以fixed形式和scientific形式输出时参数为小数位数。

setiosflags(ios::fixed)用定点方式表示实数。

setiosflags(ios::scientific)用科学记数法方式表示实数。

如果setprecision(n)与setiosflags(ios::fixed)合用,可以控制小数点右边的数字个数。

如果setprecision(n)与setiosflags(ios::scientific)合用,可以控制科学记数法中尾数的小数位数。

setiosflags(ios::left)输出数据左对齐
setiosflags(ios::right)输出数据右对齐
设置输入/输出整型数数制dec、hex和oct。

控制换行的控制符endl
代表输出单字符“\0”的控制符ends
open()函数的原型在fstream中定义。

其原型为:
void open(char *filename,int mod,int access);
其中第一个参数是用来传递文件名;第二个参数的值决定文件的使用方式;第三个参数的值决定文件的访问方式。

对于ifstream流类,mod的值为ios::in;对于ofstream流类,mod的值为ios::out。

相关文档
最新文档