文档章节

C++虚函数与纯虚函数和多态

刘大神
 刘大神
发布于 2015/05/23 11:16
字数 1109
阅读 27
收藏 0

                                           C++虚函数与纯虚函数和多态

1.多态

    多态,按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数(Virtual Function) 实现的。  

    多态特性是C++中重要的特性之一,在多态中,引用和指针的静态类型和动态类型可以是不同的,这是C++支持多态的基石。通过基类引用或指针调用基类中定义的函数时,我们并不知道执行函数的确切类型是什么,执行函数的类型可能是基类类型的,也可能是派生类型的。

    如果调用的是非虚函数,那么无论对象是什么类型的,都会执行基类类型所定义的函数。如果调用虚函数,则直到运行时,才能确定调用了哪个类型的函数,运行的虚函数是引用所绑定的或指针所指向的对象所属的类型定义的版本。

    从代码的角度来看,我们无需担心。只要正确的设计了类和函数,不管实际操作对象是基类类型的,还是派生类类型的,都将正确的工作。

 

2.C++虚函数

    上段内容中,提到了实现多态的方式--虚函数,虚函数只是其中的一种,在C++中,除了虚函数,实现多态的方式还有抽象类,覆盖,模版等。这里详细的说下虚函数的工作方式,其他不予以说明。下面来一个比较经典的关于虚函数的例子:

   1: class
   2:
   3: public
   4:     virtual void foo() 
   5:     { 
   6:         cout<<"A::foo() is called"<<endl; 
   7:     } 
   8: }; 
   9: class B:public
  10:
  11: public
  12:     void foo() 
  13:     { 
  14:         cout<<"B::foo() is called"<<endl; 
  15:     } 
  16: }; 
  17: int main(void
  18:
  19:     A *a = new B(); 
  20:     a->foo();   // 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的!   
  21:     return 0; 
  22:

    看了上面的代码,读者应该大概的理解了虚函数的作用,在派生类中,允许定义与基类同名的函数,即重写基类函数,也可以说是覆盖(override),并且可以通过基类指针或引用,调用基类和派生类中的同名的函数。

 

3.纯虚函数

       纯虚函数,其实并无什么特别的意义。拿下面这个例子来说:

   1: class 动物 {
   2:        virtual void miao() { 这里我应该写什么? }
   3: }
   4: class 猫: 动物{  xxx }
   5: class 狗: 动物{ xxx  }
这个类是动物,我们现在需要做的是让不同的动物都要做一个发出叫声的动作。 代码中应该写什么呢?因为并没有叫“动物”这种动物,所以“动物”是没有叫声的;另外,动物* a = new 动物; // 这代表了什么 ?没有 "动物" 这种 动物,你 new 猫 或者 new 狗都可以理解,但是 new 动物 表示什么 ?所以,C++引入了一个“纯虚”的标识。

class 动物 {
    virtual miao() = 0; // 函数后面写 =0
}

=0 就表示这个函数是“纯虚函数”,意思是“没有什么意义的函数”,你不需要写函数体,如果某个类, 里面有 任意一个 纯虚函数存在, 那么这个类就是 "纯虚类","纯虚类" 只有 一个 特点.那就是不能声明对象,如果你要是new对象的话,那么编译器会给你一个 error..

对于纯虚类,C++primer 书中是这么给出的定义:

                   含有(或继承)一个或多个纯虚函数的类是 抽象基类。除了作为抽象基类的派生类的对象的组成部分,不能创建抽象类型的对象。

 

 

关于虚函数,纯虚函数和多态就说这么多,如有错误,欢迎指正。

© 著作权归作者所有

刘大神
粉丝 8
博文 21
码字总数 18133
作品 0
朝阳
高级程序员
私信 提问
C++灵魂所在之---多态的前世与今生

开头先送大家一句话吧: 众所周知,在20世纪80年代早期,C++在贝尔实验室诞生了,这是一门面向对象的语言,但它又不是全新的面向对象的语言,它是在传统的语言(C语言)进行面向对象扩展而来...

loving_forever_
2016/06/13
0
0
C++学习笔记 -- 虚析构函数与纯虚析构函数

开始学C++了,所以又重拾以前学习过的相关概念… 析构函数是当一个对象的生命周期结束时,会自动执行析构函数。 析构函数的定义: #ifndef AH #define AH class A { public: A(void); A(int...

meteoric
2013/05/08
0
0
C++纯虚函数 virtual =0

C++纯虚函数 virtual =0 参考:http://hi.baidu.com/cunlin/blog/item/d82b160102e0e4037aec2ccb.html (百度空间) ====================================================================......

长平狐
2013/01/06
1K
0
重拾C++之虚函数和虚基类以及抽象类

一、引言 好久没接触过C++了,今天突然要用一点感觉号蛋疼,用惯了python感觉C++一点都不会了。 声明了一个类的对象居然用这种方法,脑子绝对是被驴(python)踢了class A{ ... } a=A();//尼...

C_Geek
2015/11/02
0
0
C++对象内存模型---数据封装

“C++是C的超集”,这句话里包含了两个问题: 1. C++兼容C; 2. C++在C之上进行了扩展; 那C++在C之上进行了哪些扩展呢?众所周知,C++内置了众多编程机制、支持众多编程风格:面向过程、基于...

rexlv
2013/05/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

GitOps 初探

前言 GitOps 的概念最初来源于 Weaveworks 的联合创始人 Alexis 在 2017 年 8 月发表的一篇博客 GitOps - Operations by Pull Request。文章介绍了 Weaveworks 的工程师如何以 Git 作为事实的...

阿里云云栖社区
33分钟前
1
0
keytool生成密钥

生成JKS Java KeyStore文件 我们首先使用命令行工具keytool生成密钥 - 更具体地说.jks文件: keytool -genkeypair -alias mytest -keyalg RSA ...

Canaan_
35分钟前
2
0
【从入门到放弃-Java】并发编程-NIO使用

前言 上文【从入门到放弃-SpringBoot】SpringBoot源码分析-请求过程中我们了解到,tomcat接收、返回请求的过程都是基于NIO实现的。日常工作中有很多基于NIO的使用,我们知道NIO可以提高系统的...

阿里云官方博客
36分钟前
3
0
mysql 如何删除数据库中所有的表

SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') FROM information_schema.tables WHERE table_schema = 'mydb'; mydb换成你想删除的数据库的名字......

RobertZhou
37分钟前
3
0
pytorch各种版本下载

链接地址:https://pytorch.org/get-started/previous-versions/

云烟成雨forever
37分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部