面向对象:类与对象 面向对象的特点 抽象、封装、继承、多态 继承与派生 提高了代码的可重用性,有利于软件开发和维护 ·派生过程:吸收父类成员、改造父类成员、添加新成员 ·构造函数,访问权限,屏蔽规侧,类型兼容规侧,虚继承 多态 函数重载、运算符重载、虚函数、模板 http://math.ecnu.edu.cn/~jypan 2
http://math.ecnu.edu.cn/~jypan 面向对象:类与对象 2 面向对象的特点 抽象、封装、继承、多态 继承与派生 ► 提高了代码的可重用性,有利于软件开发和维护 ► 派生过程:吸收父类成员、改造父类成员、添加新成员 ► 构造函数,访问权限,屏蔽规则,类型兼容规则,虚继承 多态 函数重载、运算符重载、虚函数、模板
多态(polymorphism) 多态是指同样的消息被不同类型的对象接收时会导致不同的 行为,即接口的多种不同的实现方式。比如调用具有相同函 数名的函数,但实现不同的功能。 ·消息:对类的成员函数的调用 ●不同行为:不同的实现(功能),即调用不同函数 多态的实现: 函数重载/运算符重载,虚函数/纯虚函数,模板 中多态性是面向对象程序设计的关键技术之一,若程序设计语言不支持多态性, 不能称为面向对象的语言。 http://math.ecnu.edu.cn/~jypan 3
http://math.ecnu.edu.cn/~jypan 3 多态 (polymorphism) 多态 是指同样的消息被不同类型的对象接收时会导致不同的 行为,即接口的多种不同的实现方式。比如调用具有相同函 数名的函数,但实现不同的功能。 消息:对类的成员函数的调用 不同行为:不同的实现(功能),即调用不同函数 † 多态性是面向对象程序设计的关键技术之一,若程序设计语言不支持多态性, 不能称为面向对象的语言。 多态的实现: —— 函数重载/运算符重载,虚函数/纯虚函数,模板
华东师范大学数学科学学院 目录页 School of Mathematical Sciences,ECNU Contents 虚函数 纯虚函数 模板 http://math.ecnu.edu.cn/-jypan
http://math.ecnu.edu.cn/~jypan 目录页 Contents 华东师范大学 数学科学学院 School of Mathematical Sciences, ECNU http://math.ecnu.edu.cn/~jypan 1 2 虚函数 纯虚函数 3 模板
虚函数(Virtual) 为什么虚函数: 用派生类对象替代父类的对象后,只能发挥父类的功能。 比如父类有成员函数show,派生类也有show,则用派 生类对象替代父类对象后,只能发挥父类的show功能。 如果仍然要发挥派生类的show功能呢? 虚函数 http://math.ecnu.edu.cn/~jypan 5
http://math.ecnu.edu.cn/~jypan 5 虚函数 (Virtual) 为什么虚函数: 用派生类对象替代父类的对象后,只能发挥父类的功能。 比如父类有成员函数 show,派生类也有 show,则用派 生类对象替代父类对象后,只能发挥父类的 show 功能。 如果仍然要发挥派生类的 show 功能呢? 虚函数 1
虚函数举例 ex14_virtual_fun01.cpp class Person /1父类 { virtual void show()/虚函数 { cout <<"Name:"<<name <endl; cout <<"Age:"<age<<endl; 方 class Student public Person /1派生类 virtual void show()/虚函数 Person:show(); cout <<"Stuid:"<<stuid <endl; http://math.ecnu.edu.cn/-jypan 6
http://math.ecnu.edu.cn/~jypan 6 虚函数举例 class Person // 父类 { ... ... virtual void show() // 虚函数 { cout << "Name: " << name << endl; cout << "Age: " << age << endl; } ... ... }; ex14_virtual_fun01.cpp class Student : public Person // 派生类 { ... ... virtual void show() // 虚函数 { Person::show(); cout << "Stuid: " << stuid << endl; } ... ... };
虚函数举例 ex14 virtual_fun01.cpp int main() Person p1("Gao Dai",18); Student stu1("Xi Jiajia",18,20150108); Person p; p=&p1; p->show();/父类指针p指向父类对象,调用的是父类的show() cout show();/父类指针p指向派生类对象,调用的是派生类的show() return 0; http://math.ecnu.edu.cn/~jypan 7
http://math.ecnu.edu.cn/~jypan 7 虚函数举例 int main() { Person p1("Gao Dai", 18); Student stu1("Xi Jiajia", 18, 20150108); Person * p; p = &p1; p->show(); // 父类指针p指向父类对象,调用的是父类的show() cout show(); // 父类指针p指向派生类对象,调用的是派生类的show() return 0; } ex14_virtual_fun01.cpp
几点注记 t虚函数提供了一种通过基类访问派生类功能的机制 中虚函数只能借助于指针或引用才能达到多态的效果,否则无法实现多态 ex14_virtual_fun02.cpp void fun(Person p) p->show(); /Person:show()or Student:show()? /同一段代码,可以产生不同效果→多态 推迟联编/动态联编: 一个函数的调用并不是在编译时刻被确定的,而是在程序运行时才被确定。由于 编写代码的时候并不能确定被调用的是父类的成员函数还是派生类的成员函数, 所以称为“虚”函数。 http://math.ecnu.edu.cn/~jypan 8
http://math.ecnu.edu.cn/~jypan 8 几点注记 † 虚函数提供了一种 通过基类访问派生类功能 的机制 † 虚函数只能借助于指针或引用才能达到多态的效果,否则无法实现多态 推迟联编/动态联编: 一个函数的调用并不是在编译时刻被确定的,而是在程序运行时才被确定。由于 编写代码的时候并不能确定被调用的是父类的成员函数还是派生类的成员函数, 所以称为“虚”函数。 void fun(Person * p) { p->show(); // Person:show() or Student:show()? } // 同一段代码,可以产生不同效果 多态 ex14_virtual_fun02.cpp
几点注记(续) ex14 virtual_fun03.cpp class Person { 。。。。。 virtual void show(){......} } class Student public Person { 。。 void show(){...... /可以不带virtual } 派生类中声明虚函数时,关键字virtual可以省略,这意味着,只要在父类中 声明的虚函数,则所有派生类中的同名函数(形参也相同)都是虚函数。 http://math.ecnu.edu.cn/~jypan 9
http://math.ecnu.edu.cn/~jypan 9 几点注记(续) class Person { ... ... virtual void show() { ... ... } ... ... }; class Student : public Person { ... ... void show() { ... ... } // 可以不带 virtual ... ... }; ex14_virtual_fun03.cpp † 派生类中声明虚函数时,关键字 virtual 可以省略,这意味着,只要在父类中 声明的虚函数,则所有派生类中的同名函数(形参也相同)都是虚函数
几点注记(续) ↑只需在声明处加关键字virtual,函数定义(在外部定义)时不能加 十如果派生类中没有对虚函数重新定义,则仍使用父类的虚函数 构造函数不能是虚函数,但析构函数可以 构成多态的条件 十必须存在继承关系 十继承关系中必须有虚函数,并且它们形成屏蔽关系,即父类与派生类中存在具有 相同函数原型的虚函数 ↑只能通过父类的指针或引用来调用虚函数 ex14_virtual_fun04.cpp http://math.ecnu.edu.cn/~jypan 10
http://math.ecnu.edu.cn/~jypan 10 几点注记(续) † 只需在声明处加关键字 virtual,函数定义(在外部定义)时不能加 † 如果派生类中没有对虚函数重新定义,则仍使用父类的虚函数 † 构造函数不能是虚函数,但析构函数可以 † 必须存在继承关系 † 继承关系中必须有虚函数,并且它们形成屏蔽关系,即父类与派生类中存在具有 相同函数原型的虚函数 † 只能通过父类的指针或引用来调用虚函数 构成多态的条件 ex14_virtual_fun04.cpp
2 纯虚函数 纯虚函数: ·纯虚函数用来规范派生类的行为,实际上就是所谓的“接口”,它告诉 使用者:我的派生类都会有这个函数,但具体实现由各个派生类定义。 如果类中有纯虚函数,则表示:我是一个抽象类,不能实例化! 抽象类:带有纯虚函数的类称为抽象类。 ●抽象类是一种特殊的类,它是为了抽象和设计的目的而建立的,一般处于 继承层次结构的较上层。 ·抽象类不能声明对象,只能派生。如果纯虚函数在派生类中没有实例化, 则这个派生类还是个抽象类。 ● 抽象类的主要作用是将相关功能作为接口组织在一个继承层次结构中,由 它为派生类提供一个公共的根,具体实现由派生类完成。 http://math.ecnu.edu.cn/~jypan
http://math.ecnu.edu.cn/~jypan 11 纯虚函数 纯虚函数: ► 纯虚函数用来规范派生类的行为,实际上就是所谓的“接口”,它告诉 使用者:我的派生类都会有这个函数,但具体实现由各个派生类定义。 ► 如果类中有纯虚函数,则表示:我是一个抽象类,不能实例化! 抽象类:带有纯虚函数的类称为抽象类。 抽象类是一种特殊的类,它是为了抽象和设计的目的而建立的,一般处于 继承层次结构的较上层。 抽象类不能声明对象,只能派生。如果纯虚函数在派生类中没有实例化, 则这个派生类还是个抽象类。 抽象类的主要作用是将相关功能作为接口组织在一个继承层次结构中,由 它为派生类提供一个公共的根,具体实现由派生类完成。 2