多态性与虚函数——C/C++学习笔记

多态性(polymorphism)

即:向不同对象发送同一个消息,不同的对象在接收时候会产生不同行为

所谓消息,就是函数调用。

C++中多态性就是:具有不同功能的函数可以有相同的函数名称。即实现用同一个函数名调用不同的函数内容

C++多态性分为:静态多态性 和 动态多态性

静态多态性:通过函数重载或者运算符重载实现,在编译阶段即知道函数的全部调用关系,也称为是编译时的多态性。根据表达式上下文确定该执行哪一个功能。

优点:调用速度快,效率高;缺点:缺乏灵活性。

动态多态性:在运行时实现的多态,即在运行的时候才知道操作所针对的对象。通过虚函数来实现

?

动态多态性要解决的问题是:基类有多个派生类,且允许派生类有与基类成员相同的成员名称(包括函数名称、变量名称),在运行时候用同一个成员名称调用类对象的时候,会调用哪一个对象的成员?是基类对象的成员还是派生类对象的成员?

派生类对象可以替代基类对象向基类对象的引用初始化或赋值。

虚函数就是在基类声明函数是虚拟的,并不是实际存在的函数,在派生类中才正式定义此函数。

虚函数所解决的问题是:用基类的指针,能够在指向派生类的时候,访问派生类中与基类同名的函数。

本来,若没有声明是虚函数,那么用基类的指针,则只是指向基类对象的。若用它来指向派生类,则会发生隐式类型转换,将派生类的指针转换为基类的指针。

此时,基类指针指向的是派生类对象中基类的部分。

注意:

在基类中定义的非虚函数,在派生类中被重新定义。那么,如果是用基类的指针调用该成员函数,则系统会调用对象中基类部分的成员函数;若是用派生类的指针调用该成员函数,则系统会调用派生类对象中的成员函数。这不是多态行为,因为没有用到虚函数。

动态多态的关键点在于:

  1. 虚函数、同名成员函数
  2. 基类指针
  3. 指向不同派生类时候,访问的是当前派生类对象的成员函数。

函数重载 与 虚函数  区别:

函数重载处理的是同一层次上的同名函数问题。横向重载

虚函数处理的是不同层次上的同名函数问题。纵向重载

另外注意:函数重载要求 函数的参数个数 或者 函数返回类型不同。

虚函数则要求函数名、函数类型、函数参数个数及类型都与基类虚函数必须保持一致。

使用虚函数需要注意的两点地方是:

1、只能用virtual声明类的成员函数为虚函数,不能够声明类外普通函数为虚函数。其原因是:虚函数的作用是允许派生类重新定义虚函数,显然只能够在类的继承层次之中。

2、一个成员函数被声明为虚函数之后,不能够再在同一类族中再定义一个同名的非虚函数(即函数名、参数个数、类型啥的都相同)

虚函数表

特别说明:使用虚函数是有一定空间开销的。

当一个类中带有虚函数,编译系统会为该类构造一个虚函数表(virtual function table,vtable),它是一个指针数组,存放每个虚函数的入口地址

虚析构函数

当派生类的对象从内存中清除的时候,一般是先调用派生类的析构函数,然后调用基类的析构函数。

但是,但是,但是,重要的事情说三遍。

存在这样一种情况:当用new关键词建立了临时对象,若基类中有析构函数,且定义了一个指向该基类的指针变量。在用delete 来销毁这个指针对象的时候,会发生一种情况:

系统只会执行基类的析构函数,而不执行派生类的析构函数。

因为不是虚函数,没有多态性,指针虽然赋值是派生类对象,但是只指向派生类中的基类部分。因此只是执行了基类的析构函数。

若在继承中安全地正确地执行析构函数,则最好把基类的析构函数声明为虚析构函数!!!

纯虚函数

只给出函数原型,没有函数体。在声明虚函数的时候被初始化为"=0"的函数。

声明纯虚函数的一般形式:

virtual 函数类型 函数名 (参数列表) = 0;

注意:最后有分号。纯虚函数没有函数体。=0只是个标识,告诉编译器这是个纯虚函数,没有实际意义。

纯虚函数只有函数名字不具备函数功能,不能够被调用!!!

作用是为派生类保留函数名字,以便派生类根据需要对它进行定义。如果没有保留函数名字,则不能实现多态。

凡是包含纯虚函数的类都是抽象类。抽象类不能够建立对象。

因为纯虚函数不能够被调用,所以无法实例化,即创建对象。但是,可以创建指向抽象类的指针,以此来实现多态调用。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-14 11:57:20

多态性与虚函数——C/C++学习笔记的相关文章

sdut 6-1 多态性与虚函数

6-1 多态性与虚函数 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 通过本题目的练习可以掌握多态性的概念和虚函数的定义和使用方法 要求定义一个基类Pet,它有一个成员函数Speak()用于输出pet的叫声.;派生类Dog和Cat从基类Pet派生而来.他们从基类继承并重新改写了speak()函数,分别用于输出Dog类和Cat类的叫声.要求利用虚函数编写代码,使得程序能够输出下面的内容. 输入 无 输出 输出数据共有3行,本题

sdut 6-2 多态性与虚函数

6-2 多态性与虚函数 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 通过本题目的练习可以掌握多态性的概念和虚函数的定义和使用方法 要求定义一个基类Pet,它有一个字符指针型数据成员name和一个虚成员函数Speak()用于输出pet的叫声.;派生类Dog和Cat从基类Pet派生而来.他们从基类继承并重新改写了speak()函数,分别用于输出Dog类和Cat类的叫声(具体输出内容参考示例输出).要求利用虚函数技术编写代码,使

关于C++与Java中虚函数问题的读书笔记

之前一直用C++编程,对虚函数还是一些较为肤浅的理解.可近期由于某些原因搞了下Java,发现有些知识点不熟,于是站在先驱巨人的肩上谈谈C++与Java中虚函数问题. Java中的虚函数 以下是段别人的代码,输入结果竟是Base,这让一直以来用C/C++的我有些莫不着头脑,不是Java里对象是引用吗?C/C++中通过指向基类的指针或引用来指向派生类,那么对于虚函数来说通过基类指针使用的是指向的派生类.但在Java中没有keyword标明虚函数,此时就不是非常明确究竟调用的谁. class base

【ThinkingInC++】67、多态性和虚函数

第十五章 多态性和虚函数 /** * 书本:[ThinkingInC++] * 功能:纯抽象类 * 时间:2014年10月6日13:10:28 * 作者:cutter_point */ #include <iostream> using namespace std; enum note {middleC, Csharp, Cflat}; //创建一个抽象类 //基类 class Instrument { public: //纯虚函数,不可以对纯虚函数进行传值方式的调用 virtual void

VC++ 之 多态性与虚函数

多态性是面向对象程序设计的关键技术之一.利用多态性技术,可以调用同一个函数名的函数,实现完全不同的功能.若程序设计语言不支持多态性,不能称为面向对象的语言. 在C++中有两种多态性: 编译时的多态性:通过函数的重载和运算符的重载来实现的. 运行时的多态性:在程序执行前,无法根据函数名和参数来确定该调用哪一个函数,必须在程序执行过程中,根据具体情况来动态地确定.它是通过类继承关系和虚函数来实现的,目的也是建立一种通用的程序. 虚函数的定义 ◆ 1.定义格式虚函数是一个类的成员函数,定义格式如下: 

c++特别要点:多态性与虚函数

本来是准备在工厂模式中顺便整理.但粗略浏览了,内容还是很多,需要单独开一篇. 一.什么是多态性? 多态性可以概括为“一个接口,多种方法”. 多态与非多态的区别在于“成员函数调用地址的早绑定和晚绑定”.“早绑定”在编译期就可以确定函数的调用地址,是静态的:“晚绑定”在运行时才能确定函数的调用地址,是动态的. 多态的作用是什么呢?在面向对象的编程中,“封装”使得代码模块化:“继承”可以扩展以存在的代码:“多态”使得接口重用. 二.多态性的c++实现:虚函数 声明基类的指针,该指针指向子类的对象.调用

C++学习 - 虚表,虚函数,虚函数表指针学习笔记

虚函数 虚函数就是用virtual来修饰的函数.虚函数是实现C++多态的基础. 虚表 每个类都会为自己类的虚函数创建一个表,来存放类内部的虚函数成员. 虚函数表指针 每个类在构造函数里面进行虚表和虚表指针的初始化. 下面看一段代码: // // main.cpp // VirtualTable // // Created by Alps on 15/4/14. // Copyright (c) 2015年 chen. All rights reserved. // #include <iostr

C++多态性与虚函数

面向对象程序设计中的多态性是指向不同的对象发送同一个消息,不同对象对应同一消息产生不同行为.在程序中消息就是调用函数,不同的行为就是指不同的实现方法,即执行不同的函数体.也可以这样说就是实现了"一个接口,多种方法". 从实现的角度来讲,多态可以分为两类:编译时的多态性和运行时的多态性.前者是通过静态联编来实现的,比如C++中通过函数的重载和运算符的重载.后者则是通过动态联编来实现的,在C++中运行时的多态性主要是通过虚函数来实现的. 赋值兼容     不过在说虚函数之前,先介绍一个有关

第十三周阅读项目(4):多态性与虚函数

(1)代码: #include <iostream> using namespace std; class Vehicle //交通工具 { public: void run() const { cout << "run a vehicle. "<<endl; } }; class Car: public Vehicle //汽车 { public: void run() const { cout << "run a car.