面向对象复习提纲

1.文件读写操作相关的对象、头文件,如何读取文件,如何写入文件

1、 定义数据流对象指针

对文件进行读写操作首先必须要定义一个数据流对象指针,数据流对象指针有三种类型,它们分别是:

Ifstream:表示读取文件流,使用的时候必须包含头文件“ifstream”;

Ofstream:表示文件写入流,使用的时候必须包含头文件“ofstream”;

Fstream:表示文件读取/写入流,使用的时候必须包含头文件“fstream”;

2、 打开文件

打开文件可以调用两个函数,其一是使用open函数,其二是使用数据流对象的构造函数。这两个函数调用的参数基本上一致的,以open函数为例:

参数filename表示文件名,如果该文件在目录中不存在,那么该函数会自动创建该文件;参数mode表示打开方式,这里打开方式有一下四种。

3、 文件的读写操作

由于类ofstream, ifstream 和fstream 是分别从ostream, istream 和iostream 中引申而来的,所以文件的读写操作与使用控制台函数cin和cout一样,“<<”表示对文件进行写操作,“>>”表示对文件进行读操作。

根据数据流读写的状态,有4个验证函数,它们分别是:

· bad()

如果在读写过程中出错,返回 true 。例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候。

· fail()

除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候。

· eof()

如果读文件到达文件末尾,返回true。

· good()

这是最通用的:如果调用以上任何一个函数返回true 的话,此函数返回 false 。

4、 获得或者设置流指针

获得流指针的位置有两个函数,它们是

Long tellg() 和 long tellp()这两个成员函数不用传入参数,返回pos_type 类型的值(根据ANSI-C++标准) ,就是一个整数,代表当前get 流指针的位置 (用tellg) 或 put 流指针的位置(用tellp)。

设置流指针的位置根据输入输出流指针类型不同,也有两个函数,它们是:

seekg() 和seekp()这对函数分别用来改变流指针get 和put的位置。两个函数都被重载为两种不同的原型:

seekg ( pos_type position );

seekp ( pos_type position );

使用这个原型,流指针被改变为指向从文件开始计算的一个绝对位置。要求传入的参数类型与函数 tellg 和tellp 的返回值类型相同。

seekg ( off_type offset, seekdirdirection );

seekp ( off_type offset, seekdir direction );

使用这个原型可以指定由参数direction决定的一个具体的指针开始计算的一个位移(offset),它们如表2所示。

5、关闭文件

调用函数close(),可以关闭流对象所指向的文件,释放流指针之后,那么该数据流就可以指向其它的文件进行操作了。

2.函数的重载

为什么会存在函数重载?

有时候需要根据不同的数据类型调用不同名的函数,如果这种情况比较多的话,对于写程序的人来说,要分别编写功能相同而名字不同的函数,是很不方便的。所以在c++中引入了函数重载。

那什么又是函数重载呢?

函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数、类型、顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。函数的重载即对一个函数名重新赋予它新的含义,使一个函数名可以多用。**所谓重载,其实就是“一物多用”。

3.什么是带默认值的函数

带参数默认值的函数说明:

函数有一个或多个的参数有默认值;如float Area(float r = 3.5); int Sum (int a,int b = 5, int c =10)。

带参数默认值函数注意:

1、默认值参数只能放在函数声明或定义处,一般放在函数声明中。

一般情况,调用方只能看到函数声明,如果写在函数定义中,调用方不知道默认参数是什么;如果默认参数写在函数定义处,函数声明(无默认参数)无法确定这个函数是带默认参数的。

2、默认参数规则:

a、自右向左,依次赋值。(调用参数传递参数是从左到右的,所以没有默认参数都必须传值进来)

b、默认值只能赋值一次。

c、默认值可以使用全局变量、函数返回值。

4.const的不同用法

1.const 修饰成员变量

2.const修饰函数参数

  传递过来的参数在函数内不可以改变,与上面修饰变量时的性质一样。

3.const修饰成员函数

(1)const修饰的成员函数不能修改任何的成员变量(mutable修饰的变量除外)

(2)const成员函数不能调用非onst成员函数,因为非const成员函数可以会修改成员变量

4.const修饰函数返回值

(1)指针传递

如果返回const data,non-const pointer,返回值也必须赋给const data,non-const pointer。因为指针指向的数据是常量不能修改。

(2)值传递

 如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const 修饰没有任何价值。所以,对于值传递来说,加const没有太多意义。

所以:

  不要把函数int GetInt(void) 写成const int GetInt(void)。
  不要把函数A GetA(void) 写成const A GetA(void),其中A 为用户自定义的数据类型。

5.static的不同用法

面向对象中的static

静态全局变量

(1)该变量在全局数据区分配内存;具有全局寿命;

(2)未经过初始化的静态全局变量,默认初始化为0;

(3)a为静态变量,并且是全局的,只能在定义a的文件中使用a,在其他的文件中不可见

静态局部变量

(1)静态局部变量在全局数据区分配内存,具有全局寿命;

(2)静态局部变量在对象被第一次声明时初始化,以后的调用都不用再初始化。

(3)未被初始化的静态局部变量,默认初始化为0;

静态函数

只能在定义它的文件中使用,在其他文件不可见。

面向过程中的static(在类中使用)

静态数据成员

(1)非静态数据成员,每个类对象都有自己的拷贝。然而静态数据成员,不管这个类被对象被定义了多少次,都只有一个拷贝,所有对象共享这一个拷贝,所有对象共用,它的值可以更新。

(2)静态数据成员存储在全局数据区,不能再类的声明中定义。语句int Point::countP = 0;是定义静态数据成员。

(3)由于静态数据成员在全局数据区分配内存,所以它不属于特定对象,在没有类的实例情况下就可以操作它。

(4)静态数据成员初始化格式:

<数据类型><类名>::<静态数据成员名>=<值>

注意只能在全局区初始化,不可以在类内部初始化。

访问形式:

<类对象名>.<静态数据成员名>

<类对象指针> -> <静态数据成员名>

<类名>::<静态数据成员名>

(5)静态数据成员同样遵循public、protected、private访问规则。

静态成员函数

与静态数据成员规则一样。

访问形式:

<类名称>::<静态成员函数名>(参数列表);

类对象操作符.  和该对象指针 ->

 

6.类定义时候,文件的访问控制public,private,protect的意义

private, public, protected 访问标号的访问范围。

private:只能由(1)该类中的函数、(2)其友元函数访问。
不能被任何其他访问,该类的对象也不能访问。

protected:可以被(1)该类中的函数、(2)子类的函数、以及(3)其友元函数访问。但不能被该类的对象访问。

public:可以被(1)该类中的函数、(2)子类的函数、(3)其友元函数访问,也可以由(4)该类的对象访问。

注:友元函数包括3种:设为友元的普通的非成员函数;设为友元的其他类的成员函数;设为友元类中的所有成员函数。

 

7.类的继承中,public,private,protected继承的意义

类的继承后方法属性变化。

可以将类的继承想象为对父类对象的访问。不说是private继承后父类的protected和public属性在子类中变为private,因为子类可以访问自身的private,就说它可以访问父类的private属性。对于父类,它被子类继承之后属性发生变化,这种变化直接的影响是子类在访问父类的时候访问权限受限了,如果要求父类的原本的权限,就应使用public继承方式。

private 属性不能够被继承。
使用private继承,父类的protected和public属性在子类中变为private;
使用protected继承,父类的protected和public属性在子类中变为protected;
使用public继承,父类中的protected和public属性不发生改变;

如下所示:
public: protected: private:
public继承 public protected 不可用
protected继承 protected protected 不可用
private继承 private private 不可用

protected继承和private继承能降低访问权限。

 

8.怎样给类的数据成员赋初值

类中以下成员必须放在初始化列表中初始化:

        (a)引用数据成员 (b)  const 数据成员

  (c)基类没有显示的构造函数,必须在派生类的构造函数中初始化基类构造函数

       (d)类类型成员(该类没有缺省的构造函数)  因为初始化不必调用默认构造函数来初始化,直接调用拷贝构造函数   

 

9.类的构造函数、析构函数

 一 构造函数  

 1 构造函数: 构造函数时一个特殊的成员函数,用来初始化对象的数据成员,在对象创建时,由编译器自动调用,在对象的生命周期且只调用一次。

  定义构造函数的原型的格式: 类名(形参列表);   

   在类外定义构造函数的格式:类名::类名(形参列表)  {} 

  2 构造函数的特点:

    (1)函数名与类名相同;

    (2)没有返回值,也不能指定为void类型;

    (3)有初始化列表 

初始化顺序:(1)每个成员在初始化列表中只能出现一次 

                (2)数据成员在类中定义的顺序就是参数列表中的初始化顺序

(4)构造函数可以重载,默认参数只能在原型声明中指定,不能在函数定义中指定。

   (5)无参构造函数和带缺省的构造函数都认为是缺省构造函数,并且缺省构造函数只能有一个

 (6)构造函数不能用const 修饰

 3 构造函数的作用 :构建对象,初始化对象,类型转换 

 二、析构函数

1. 析构函数:与构造函数的功能相反,在对象销毁时,由编译器自动调用,完成类的一些资源清理和汕尾工作。

注意:析构函数的目的是在系统回收对象 内存之前执行结束清理工作,以便内存可被重新用于保存新对象。

2 特性 

a 析构函数没有参数没有返回值,函数名是类名前加上`.

b 一个类有且只有一个析构函数。若未显示定义,系统会自动生成缺省的析构函数。

c析构函数并不是删除对象,只是做一些清理工作。

d 调用次序与构造函数相反,最先构造的对象最后被析构。

三、 赋值运算符重载

c++中,对于任何一个类,如果没有用户自定义的赋值运算符函数,系统会自动的生成一个默认的(默认的完成的数据成员的逐位复制)。特殊情况下:如类中有指针形式就不能直接相互赋值,不然可能造成指针悬挂问题。

注意:(1)赋值运算符不能重载为友元函数,只能重载为一个非静态成员函数。

   (2)赋值运算符重载函数不能被继承。

10.对象可以访问类的哪些成员

C++中类访问权限控制:
第一:private, public, protected 访问标号的访问范围,在没有继承的情况下:
private:
只能由1.该类中的函数、2.其友元函数访问。
不能被任何其他访问,该类的对象也不能访问。
protected:
可以被1.该类中的函数、2.子类的函数、以及3.其友元函数访问。
但不能被该类的对象访问。
public:
可以被1.该类中的函数、2.子类的函数、3.其友元函数访问,也可以由4.该类的对象访问。
 注:友元函数包括3种:设为友元的普通的非成员函数;设为友元的其他类的成员函数;设为友元类中的所有成员函数。
第二:类的继承后方法属性变化,具体情况如下:
private 属性是不能够被继承的,protected继承和private继承能降低访问权限。
使用private继承,父类的protected和public属性在子类中变为private;
使用protected继承,父类的protected和public属性在子类中变为protected;
使用public继承,父类中的protected和public属性不发生改变; 
 如下所示: 
                   public:        protected:       private:
public继承          public        protected        不可用 
protected继承       protected     protected        不可用 
private继承         private       private          不可用 

 

11、是什么,在类外定时成员函数时,如何用类名::限定成员函数

(1).函数在类内定义和在类外定义效果是一样的,只是对于较长的程序函数放在类外更有利于读程序;

(2).在类外定义成员函数时必须现在类内写出成员函数的原型声明,然后再在类外定义;

( 3).如果在类外有定义,但是在函数名前没有类名和作用域运算符,则该函数被认为是普通函数;

 (4).在类内声明成员函数,在类外定义成员函数,是软件工程中良好的编程风格

 

12.运算符重载,能改变原有操作符本身的操作数个数、优先级吗?

(1) 并不是所有的运算符都可以重载。

(2) 重载不能改变运算符的优先级和结合性。

(3) 重载不会改变运算符的用法,原有有操作数个数不变。

(4) 运算符重载函数不能有默认的参数,否则就改变了运算符操作数的个数,这显然是错误的。

(5) 运算符重载函数既可以作为类的成员函数,也可以作为全局函数。

 

13.什么是友元函数

(1)友元函数

友元函数不是类的成员函数,而是类的外部函数。友元函数可以访问该类的私有成员。

(2)友元类

和友元函数类似。如将类A声明为类B的友元类,那么类A就可以访问类B的私有成员。而且类A中的所有成员函数都是类B的友元函数。

注意:(1)友元关系是单向的,即你是我的友元,但是不能推出我就是你的友元。(2)友元关系不能继承,即你是我的友元,但是不能推出你的子类也是我的友元。

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend,其格式如下:

       friend 类型 函数名(形式参数);

       友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数。

       一个函数可以是多个类的友元函数,只需要在各个类中分别声明。

       友元函数的调用与一般函数的调用方式和原理一致。

友元类 : 

       友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。       

       当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:

       friend class 类名;

       其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。

猜你喜欢

转载自blog.csdn.net/Zra___/article/details/106901423