第三章总结下

来源:互联网 发布:大数据分析彩票 编辑:程序博客网 时间:2024/05/22 03:05

33继承

3.3.1继承的基本知识

1.继承的概念

继承是指在已有的类的基础上建立新类,新类自动得到已有类的全部操作和数据然后再定义已有类中没有的成员,这样就能大大节省程序开发的时间和生成。

继承是面向对象程序设计的基本特征之一,是代码重用的重要机制。一个派生类可以从一个基类派生,称为单继承;也可以从一个基类派生,称为单继承,也可以从多个基类派生,称为多继承。

单继承的定义格式:

Class<派生类名>:<继承方式><基类名>

{

       派生类新定义成员

};

4.派生类中基类成员的访问权限

1)派生类的成员函数能访问基类中的publicprotectedprivate成员属于基类私有,派生类不可访问。

2)若为public访问权限,则通过派生类的对象可以访问,若为protectedprivate访问权限,则通过派生类的对象不可访问。

3.3.2派生类的构造与析构

1.派生类的析构函数

析构函数不能够被继承,派生类的构造函数必须通过调用基类的构造函数类初始化基类子对象:

<派生类名>(<派生类构造函数总参数表>):<基类构造函数>(<参数表1>)

{

       <派生类中数据成员初始化>

}

派生类构造函数的调用顺序为:先调用基类的构造函数然后在执行派生类构造函数体中的内容,当基类的构造函数有一个或多个参数时则派生类必须定义构造函数以便向基类构造函数传递参数。

2.派生类的析构造函数

在销毁派生类指定多个基类,这样的继承结构称为多继承,可看作单继承的扩展,派生类与每个基类之间的关系仍可看作是一个单继承

多继承的定义格式如下:

Class<派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,……

{

       //派生类新定义成员

}

2.多继承的构造函数与析构函数

多继承的构造函数格式如下:

<派生类名>(<总参数表>):<基类名1>(<参数表1>),<基类名>(<参数表2>),……

{

<派生类构造函数体>

};

执行顺序是先执行所有基类的构造函数,在执行派生类本身的构造函数。

多继承条件:派生类对象销毁时,析构函数执行顺序与构造函数的执行顺序严格相反。

3.二义性

多继承条件下,若两个或多个基类中有同名成员访问这类成员时成员名前必须有“基类名::”,即用成员名限定,否则,编译器将搞不清要访问哪个基类的成员,即产生二义性错误。

3.3.5虚基类

1.虚基类的概念

当一个派生类从多个基类派生,而这些基类又有一个共同的基类时,这个派生类对象将拥有多份最初基类子对象,对最初基类对象成员的访问必须用其派生类作为成员名限定。

虚基类的语法为:

Class<派生类名>:virtual<继承方式><基类名>

{

       //派生类新成员的定义

}

3.3.6类型兼容

对一个操作类型为基类对象的程序段,如果将派生类的对象交给这段程序处理,丝毫不会影响到这个程序段的功能。

eg.有以下基类八色和其公有派生类derived

class 八色{……;

class  derived : public base{……};

(1)       派生类的对象可以赋值给基类的对象;

derived d;

 base  b;

 b=d ;

(2)派生类的对象可以初始化基类的引用

Derived  d

Base&  br=d

3)派生类对象的地址可以赋值给基类的指针

Derived d

Base *pd=&d

3.4虚函数与多态性

3.4.1虚函数

1.为了能通过基类指针调用派生类的成员函数,须在基类中将某些函数声明为虚函数方法是在函数声明前加上关键字virtual

A基类指针实际指向一个基类对象时则调用基类中定义的虚函数

B基类指针实际指向一个派生类对象时,则调用派生类中定义的虚函数,若派生类内未定义这一虚函数,则调用基类的虚函数。

2.虚函数的注意事项

A只能指定类的成员函数为虚函数,类的静态成员函数和全局函数不能指定为虚函数,若虚函数的定义和声明是分开的,只能在声明部分使用关键子virtual

B若基类的一个函数声明为虚函数,派生类的改写版自动为虚函数

C在派生类中重新定义虚函数时,必须保证新函数的函数原形与基类中虚函数的原形一致,否则就属于重载(参数与基类的虚函数不同时)或是一个错误(返回值与基类的虚函数不同时)。

D构造函数不能说明为虚函数,但析构函数可以。

3.4.2虚析构函数

析构函数可以声明为虚函数,这样其派生类的析构函数自动成为虚函数將析构函数生命为虚函数的目的是使用的是使用delete操作符删除一个对象时,能保证对象所属类的析构函数被正确地执行

3.4.3纯虚函数与抽象类

1.纯虚函数

如果一个虚函数在定义时不给出函数体,而代之以“=0;”表示则该虚函数称为纯虚函数

2.抽象类

拥有纯虚函数的类称抽象类。抽象类不能定义对象,但可以用来定义只有某些标准接口。

3.4.4多态性

同一段代码,当用不同的对象去调用时,该代码具有不同的功能,这称为多态性编译十恶多态通过函数重载和模版实现,运行事多态通过虚函数来实现。

1.       函数重载实现多态,对同一个函数名,当用不同的实参调用时,会调用到不同的重载函数版本,因而完成不同的功能,这是一种多态性的体现

2.       模版实现多态,模版是一类函数或类的样板,通过用不同的模版实参调用模版同一名字可生成不同的函数或类,从而实现不同的功能。

3.       虚函数实现多态,通过动态束定机制,是相同的函数调用代码可能调用不同的类(基类或派生类)的虚函数从而完成不同的功能。

3.5运算符重载

3.5.1运算符重载的概念

对于系统预定义的数据类型,系统提供了预定义的运算符以完成各种运算

int x=3,y=5,z;

z=x+y

该语句为了实现将两个整数相加的功能C++系统通过调用内部的一个函数operator+(int,int)来完成上式中操作符“+”的功能

C++系统中,操作符的功能是通过函数实现的,且函数的名字有关键字operator加上操作符的名字构成,这样的函数也称为操作符函数

3.5.2运算符重载的基本方法

重载为类的友元函数和重载为类的成员函数

1.       重载为类的友元函数

运算符重载为类的友元函数的语法如下:

   Friend<函数类型>operator<运算符>(<形参表>)

{

       <函数类>;

}

2.       重载为类的成员函数

运算符重载为类的成员函数语法如下:

<函数类型>operator<运算符>(<形参表>)

{

       <函数体>;

}

3.       关于运算符重载的说明

3.5.3特殊运算符的重载

1.重载赋值运算符“=

C++允许同类对象之间相互赋值

A     a1(10), a2(20);

a1=a2

将“=”右侧对象的每一个成员对应赋给左侧的对象,使两个对象完全一样

2.重载增11运算符

++”和“--”运算符的重载有前缀和后缀两种形式,重载时须额外提供一个参数来加以区分被重载的运算符是前缀还是后缀。

<函数类型>operator++();前缀运算

<函数类型>operator++();后缀运算

使用前缀运算符的语法格式为:++<对象>

使用后缀运算符的语法格式为:<对象>++;

使用前缀“++”时,对操作数(对象)进行增量修改,然后再返回该对象的引用,参数与返回值是同一个对象

使用后缀“++”时,需要创建一个临时对象,存放原有对象的值然后对操作数(对象)进行增修改,最后返回保存在临时对象内的操作数值。

前缀“++”重载返回值为引用,所以可以连续进行“++”操作

3.6模版与异常

模版是函数或类的“样板”,通过它快速复制出大量结构相同但参数类型不同的函数或类,从而避免针对相同的操作去每一种数据类型定义一个单独的函数或类的麻烦。

2.函数模版

函数模版中,允许将函数的参数或返回值类型定义为一种类型变量,然后针对该类型变量定义函数体的结构。

函数模版形式如下

template<模版形参表>

<返回值类型><函数名>(模板函数形参表)

{

//函数定义体

}

3.6.2异常

1.C++的异常机制用来处理程序中可以预料的错误,比如要打开的文件不存在,除法除数为0等。

对于这类错误。C语言中

2.异常的处理语法

C++程序中,任何需要检测异常的语句都必须放在try语句快中异常由紧跟着try语句后面的catch语句块来捕获并处理

Trycatch结合使用

try

{

       //try语句块

//throw(表达式)

}

catch(类型1参数1)

{

       //针对类型1的异常处理

}

catch(类型2参数2)

{

//针对类型2异常处理

}

Catch(类型n参数n)

{

       //针对类型n的异常处理

}

说明:

1.       try块内的语句引发的异常将不被捕获

2.       如果try块内的语句在执行期间没有引起异常,那么跟在try块后的catch字句就不执行,程序从最后一个catch字句后面的语句继续执行下去。

3.       如果try块内的语句引发异常,则在抛出带你创建对象(throw语句的参数),C++系统检查try块后的catch子句,寻找一个捕获参数类型与抛出异常类型一致的catch子句若找到则转入此子句进行异常处理,若找不到则依次向上搜索try块所在函数的调用者。

4.       如果最终没找到匹配没找到匹配的catch子句,则这个异常交由C++系统处理,通常是简单地将程序终止。

5.       如果找到了一个匹配的catch处理程序,则转入这个catch处理程序执行,catch子句执行完后程序跳转到跟随在最后一个catch子句之后的语句执行。

6.       catch处理程序的出现顺序很重要,因为异常处理程序是按照它们出现的先后顺序依次检查的。