面向对象编程与面向过程的一个根本区别,就是面向对象编程在虚拟的计算机世界构造出了形形×××的对象,很显然这些对象之间必然要发生关系,如何区别描述这些关系也是面向对象这门课所要研究的问题。我们都知道其中有非常多的概念,有些概念还非常抽象,根本难以理解,特别是如果逻辑思维不好的话,会根本被这些概念绕进去。那么这里我们怎么去理解这些东西呢?以我的经验,我想我们还是从生活来理解,我们相像一下计算机描述的世界同现实世界是一模一样的。我们讲两个人,比喻说你和你爸是父子关系,那你的朋友张三与张三的爸是不是也是父子关系呢,当你描述你的某样特征继承你爸时候,实际上这种继承关系也发生在张三与张三的爸之上。那么你可能会说,我们两者之间继承的肯定不一样啊,是的,继承的结果是不一样的,但继承的逻辑是一样的。由此我们推出在现实世界中描述继承虽然理解上好像是两个对象之间的事情,但实际上它的逻辑映射是类结构上。所以讨论计算机中C++语言中的继承也一样,它也是通过描述两个不同的类之间关系,来映射出两个对象之间继承结果。因此,两个类之间具有继承逻辑定义,就说明由这两个类创建的对象具有继承的结果,这个结果就是作为子类生成子对象可以访问作为父类的父对象一些特定函数和属性。这样理解,也可能会让你产生一种误会,比喻,说你跟你爸,你能访问你爸什么呢?显然这里的访问不能作交互理解,更多的理解是你具有了父亲的一些特征。所以说子类创建的对象自然具有了父类的函数与属性。定义一个派生类的格式:

class 派生类名:继承方式(public/protect/private):父类名

{

派生成员函数;

派生成员数据;

}

从上面的格式来看,继承方式同前面的控制属性使用相同的关键字。那么它们两者之间有什么关联呢?我们前面说控制属性是站在两个对象能否相互访问的立场来看,比喻说一个属性或者一个函数,是public,那么另外的对象它是可以直接访问到这个对象的。那么前面所说的继承方式是不是也一样呢?显然不一样,因为前面的控制属性是两个对象之间,而现在继承方式是两个类之间,明显类是一种抽象概念,是不具有访问控制这一说法。类只是通过函数表现某种继承特征。这一点,我们可以这样相像,比喻说爸爸有双眼皮,那么儿子可能有双眼皮,也可能没有。从双眼皮这个特征上说,它在子类中表现为可以具备也可能不具备。因此,继承方式实际上表明了父类中的某个函数在子类中因为继承方式的不同,子类可能不具备父类的某个函数特征。所以C++设计了三个不同的继承方式,通过这三个不同方式,子类有选择的继承了父类的不同特征。具体概念要求就是子类降一级。具体如下:

【1】public(公有继承):继承时保持基类中各成员属性不变,外部类对象可以通过继承类对象访问基类的公有和保护成员,但不能访问基类中private成员。派生类的其它成员函数也可以访问基类中public和protect成员,但不能访问private成员。

【2】protect(保护继承):继承时基类中的public和protect成员在派生类中变成protect,外部类对象不能通过派生类对象访问基类所有成员,但派生类其它成员函数可以访问基类中的public和protect成员,同样也不能访问private成员

【3】private(私有继承):继承时基类中的public和protect成员在派生类中变成private,外部类对象不能通过派生类对象访问基类所有成员,但派生类其它成员函数可以访问基类中的public和protect成员,同样也不能访问private成员。那可能有人会问私有继承与保护继承有什么区别,这里区别在于C++是有多种继承,实际上进行了私有继承,就不可以再往下继承了。

前面我们讲述了派生类与子类之间关于继承方式不同而影响到不同的控制属性。那么接下来我们思考三个问题?而这三个问题显然非常明显,都具有共同性,就是同名属性与现名函数问题。我们分成三个点来学习:

【1】构造函数 父类与子类都具有构造函数,并且构造函数还一样,入参不一样。那么很显然,子类对象初始化时如何构造子类,而子类构造函数怎么构造父类构造函数。这就说出另一个问题,就是基类的构造函数能否被继承呢?按照前面的理解,似乎构造构造函数只要不是private都可以继承,但实际上构造函数是不能继承的,为什么构造函数不能被继承,这一点需要从构造函数的出发点来说明,构造函数它不是普通的成员函数,它是在创建对象时调用的,也就是说它是编译器特定的一种函数,它是由编译器来控制的函数,只有当类实例化成对象时,构造函数才会被调用。所以如果子类能继承基类构造函数,当基类创建对象时就会同时创建出一个父类对象出来,这是不可能的 。对象只有一个。那么学过C++的人都知道,实际上子类构造函数是可以调用父类构造函数进行初始化的,那这种调用其出发点是干什么呢?因为子类的构造函数在构造子类对象时,因为子类继承了父类的一些特定成员,这些成员需要通过父类的构造函数才能初始化。所以子类需要通过父类的构造函数构造出父类的成员来。

【2】同名成员属性或者多继承时来自共同祖先但不同中间祖先,如下图所示中x属性,在A对象和B对象都有,显然,C对象中x是继承自哪个父类呢?从下图中显然说不清楚?

上图是继承的两个父类具有相同成员属性。那么三重继承中最上层的属性肯定被中间层继承,最底层的类如果使用祖先类成员又会分不清楚哪个父亲了。

我们必须避免这种情况,避免这种情况有一种方法可以使用A::x来调用指定来自哪个继承父类。对后面一种情况,多重继承我们还有另外一种说法,就是虽然有两个父亲,但我只想一个祖先成员。这时候可以使用虚继承。

【3】同名函数 显然父类与子类是一定会出现同名函数,并且这些同名函数还具有相同的形参。那么如果子类继承了父类的同名函数,对子类对象来说,使用这个同名函数究竟是父类的函数还是子类的呢?这里面有什么规律呢?

同名函数在覆盖的前提下,对由不同层次的类生成的对象调用的都是自身的函数,而不是继承来的函数。但是我们还有一种类型自动转型概念,这个是C++这种动态语言的一个特点,比喻说 A p*; B b; p=&b;这时候虽然指针p的类型还是A,但是已经指向b 对象了,那么这种情况下同名函数是哪一个呢?令人惊讶的是这时候它还是A的output函数,这时候它就不具有多态性。这一点,如果想不通的话,可能需要借助汇编或者编译器去了解底层实现细节。

要想实现在指针或者引用的条件,同名函数使用真实对象自身的同名函数,需要将其基类的函数声明为虚函数 virtual。虚函数是指当某个函数在不同层次的类中完全相同时,在程序执行时根据不同对象,应该调用哪个层次的函数时,我们采用了一种虚函数的机制。如果这个函数不加vitual,则通过指针或者引用来调用这个函数时,这个函数只具备一态性。而如果这个函数加了virtual,则通过指针或者引用来调用这个函数时,这个函数具备多态性。从虚函数可以实现多态性的情况,如果基类内部函数全部是虚函数,并且这些虚函数都没有实现,也就是纯虚函数时,这个类一般称之为抽像类。抽象类通常是不能产生对象的,但是可以声明指针,并通过指针指向抽象类的子类,实现多态性。

转载于:https://blog.51cto.com/acreep/711371

C++语言基本概念(5)相关推荐

  1. c语言字符变量grade如何定义,c语言基础概念笔记

    最近看到自己之前刚开始学习的时候记的一些笔记就稍微整理了一下 第一章 c语言注释 概念:给代码进行解释说明 作用:加强程序代码的可读性和维护性 /*:多行注释 //:单行注释 变量和基本数据类型 变量 ...

  2. java 注解 demo_JAVA语言注解概念使用及Demo讲解

    本文主要向大家介绍了JAVA语言注解概念使用及Demo讲解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. java注解 概念 Java提供了一种原程序中的元素关联任何消息和任何元数据 ...

  3. c语言从入门到精通_C语言基本概念(上)【C语言入门到精通】

    C语言基本概念 Syntactic sugar causes cancer of the semi-colons.[0] 码字不易,对你有帮助 点赞/转发/关注 支持一下作者 微信搜公众号:不会编程的 ...

  4. python中动态语言静态语言的定义_作为程序开发,你所需要知道的编译型与解释型、动态语言与静态语言、强类型语言与弱类型语言的概念以及区别...

    作为程序开发,你所需要知道的编译型与解释型.动态语言与静态语言.强类型语言与弱类型语言的概念以及区别! 在各式各样的开发过程当中,我相信各位开发小伙伴在开发过程中并没有太关注什么是解释性语言和编译性语 ...

  5. JAVA数组概念与C语言数组概念区别

    C语言数组概念: 数组是一个集合数据类型,它由多个元素组成,每个元素都有相同的数据类型,占有相同大小的存储单元,且在内存中连续存放.每个数组都有一个名字,数组中的每个元素都有一个序号(都成为下标),表 ...

  6. C系列(1)----C语言基本概念

    经过几个月对C语言的学习,施律.打算对c语言的内容通过博客的形式作一个较为详细的讲述.本系列的博客有20余篇(暂定).2-3天更新一篇.篇与篇之间的联系还是比较大的,会出现前后穿插的现象.希望正在学c ...

  7. C语言指针概念全面解析

    C语言指针的概念 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址.要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本 ...

  8. JS中的函数概念和C语言的概念是类似的,c语言和JavaScript的区别有哪些?

    c语言和JavaScript在语法结构上有很多相似(例如if条件语句.while循环.switch语句.do-while循环等),那么它们之间有什么不同?下面本篇文章就来给大家介绍一下c语言和Java ...

  9. [程序设计语言]-[核心概念]-04:数据类型

    0. 概述 为何高级语言需要类型系统这个概念?在汇编时代是没有完整的数据类型系统的,结构化编程引入了结构化的控制流.为结构化设计的子程序,随之这种结构化的代码所操作的数据也进一步的"抽象化. ...

最新文章

  1. util.sh 脚本
  2. Java初学者必看2
  3. 监控io性能, free命令, ps命令, 查看网络状态, linux下抓包
  4. C语言 int 转单精度浮点,单精度浮点数与十六进制转换 C语言程序 单片机也可用...
  5. JPA基础(八):分析JPA与持久化实现产品对接的源代码
  6. 疲劳驾驶数据集_人工检查,11 个类、97942 个标签,Roboflow 开源自动驾驶数据集可以使用啦...
  7. ITK:查找图像的更高导数
  8. 浅拷贝和深拷贝的区别_深拷贝和浅拷贝的区别
  9. JavaScript中OOP——面向对象中的继承/闭包
  10. 51nod 1046 A^B Mod C
  11. 在线图片转base64工具
  12. Spring Data JPA实战视频教程
  13. 仿Tumblr点赞心破碎动画
  14. 中国平安银行关于软件测试笔试试题(二)
  15. mysql 立方根函数_Java实现牛顿迭代法求解平方根、立方根
  16. 2022 综合英语慕课(大学英语二)最新满分章节测试答案(题库中自找具体题目)
  17. Cisco ❀ MPLS中的路由器角色
  18. 存储过程排版工具_文案创作者必备的7个写作辅助工具类网站,记得收藏
  19. 转:python提取浏览器Cookie
  20. 电脑测试软件pcmark,Pcmark10(电脑性能测试软件)

热门文章

  1. auto_ptr解析
  2. 射灯安装方法图解_江苏天筑不锈钢雕塑厂家格栅射灯安装方法,格栅射灯安装注意事项...
  3. python3 爬虫 requests安装_BOSS直聘招聘信息获取之爬虫工具分析
  4. java 获取六个月账期,应收帐龄分析里面账期分析能不能改为0-30天?
  5. delphi7存取配置文件与sqlserver数据库连接_Delphi7存取配置文件与SQLServer数据库连接...
  6. Spring中的InitializingBean接口的使用
  7. GC的作用域,方法区和堆
  8. linux安装mysql不成功怎么处理_Linux上安装MySQL时出现不兼容的解决办法
  9. 后端:请谨慎使用Arrays.asList、ArrayList的subList
  10. swagger 使用指南