文档章节

面向对象的三大特性及多态的理解和原理剖析

沙米笔记
 沙米笔记
发布于 2016/05/08 16:21
字数 1647
阅读 301
收藏 9
点赞 2
评论 0

面向对象的三大特性

1、封装    突破了函数的概念

    把客观事物封装成抽象的类,通过访问控制符把自己的成员变量和函数提供给可信的类和对象来操作,对不可信的进行信息隐藏。

2、继承    实现了以前代码的复用

    通过继承可以使用现有类的所有功能和成员变量(当然也需要看访问控制符),并在无需重新编写原来的类的情况下对这些功能进行扩展。

3、多态    实现了对后来的代码的复用

    多态表现为同样的调用语句,有多种不同的调用方式

    例如:80年代的人写的框架,90年代的框架什么都不需要变,只需要根据业务需要继承以前的父类,重写父类以前的方法,将子类对象指针(或引用)传入框架即可。

 

多态相关的知识

重载、重写、重定义联系和区别

重载1、必须在一个类中

          2、函数名字相同,参数列表不同(参数的类型、顺序、个数决定),返回类型可同可不同,virtual关键字可有可无.

          3、在编译期间就确定了调用了具体的某个函数。

  注意:子类不能重载父类的函数(如果子类和父类中的函数名字相同,子类将会把父类的名称覆盖,占用了父类函数的位置,此同名函数只有子类的函数可以调用,父类的将不能被调用(如果要调用必须添加域名)

重写1、必须在两个类中且具有继承关系

          2、方法名、参数个数和参数类型 都必须相同

          3、 基类函数必须有virtual关键字

重定义(隐藏):

        1、如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏

         2、如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有vitual关键字,此时,基类的函数被隐藏

多态:符合重写规则,要有父类引用(指针)指向子类对象。

静态联编和动态联编

静态联编:在编译器编译阶段,已经决定了函数的调用(不写virtual关键字,是静态联编)

动态联编:在运行阶段,根据具体的对象(具体的类型),执行不同对象的函数,表现为多态

 

为什么需要多态

如果没有多态,C++编译器只能根据我们调用语句具体的对象类型,调用具体对象的方法(如父类对象只能调用父类的print方法,子类对象只能调用子类的print方法),

而不能对同样的调用语句,有多种不同的调用方式(父类对象可以调用子类的print方法)

代码如下(没有使用多态)

#include <iostream>
using namespace std;

class Parent    //父类
{
public:
	 void print()
	{
		cout<<"parent print..."<<endl;
	}
};

class Child:public Parent    //子类
{
public:
	 void print()
	{
		cout<<"child print..."<<endl;
	}
};

void playObj(Parent* p)    //调用函数
{
	p->print();
}

int main()
{
	Parent par;
	Child  chld;
	playObj(&par);    //调用函数传入父类对象指针
	playObj(&chld);    //调用函数传入子类对象指针
	system("pause");
	return 0;
}

使用多态后代码(只是加了virtual关键字)

#include <iostream>
using namespace std;

class Parent    //父类
{
public:
	 virtual void print()    多态,在重写的函数前加virtual关键字 
	{
		cout<<"parent print..."<<endl;
	}
};

class Child:public Parent    //子类
{
public:
	 virtual void print()    //多态,在重写的函数前加virtual关键字 
	{
		cout<<"child  print..."<<endl;
	}
};

void playObj(Parent* p)    //调用函数
{
	p->print();
}

int main()
{
	Parent par;
	Child  chld;
	playObj(&par);    //调用函数传入父类对象指针
	playObj(&chld);    //调用函数传入子类对象指针
	system("pause");
	return 0;
}

多态成立条件

1、要有继承         上例中类Child继承了类Parent

2、要有函数重写(虚函数)  上例中子类重写了父类的虚函数print()

3、要有父类指针(父类引用)指向子类对象 上例中Parent* p指向了子类对象chld

多态意义

实现了接口重用(统一的表达式),接口重用带来的好处是程序更易于扩展,代码重用更加方便,更具有灵活性。

接口是最有价值的资源,只要定义好了接口,可以省去很多人力物力去做重复的事情。

多态原理剖析

1、当类中声明虚函数时,编译器会在类中生成一个虚函数表

2、虚函数表是一个存储类成员函数指针的数据结构

3、当实例化对象时,如果此对象类存在虚函数时,则此对象中会生成一个指向虚函数表的指针C++编译器给父类对象、子类对象提前布局vptr指针

4、当进行playObj(animal *pAnimal)函数是,C++编译器不需要区分子类对象或者父类对象,只需要在pAnimal指针中,找vptr指针即可

代码如下:

#include <iostream>
using namespace std;

class animal
{
public:
	virtual void  cry()		//声明虚函数时,编译器会在类中生成一个虚函数表
	{
		cout<<"animal cry..."<<endl;
	}
};

class dog:public animal
{
public:
	virtual void cry()		//声明虚函数时,编译器会在类中生成一个虚函数表
	{
		cout<<"dog cry...  wang wang "<<endl;
	}
};

class cat:public animal
{
public:
	virtual void cry()		//声明虚函数时,编译器会在类中生成一个虚函数表
	{
		cout<<"cat cry...  miao miao "<<endl;
	}
};

void playObj(animal *pAnimal)
{
	pAnimal->cry();		//C++编译器不需要区分子类对象或者父类对象,只需要在pAnimal指针中,找vptr指针即可
}

int main()
{
	cat cc;		//实例化对象cc,在对象中会生成一个指向虚函数表的vptr指针
	dog dd;		//实例化对象dd,在对象中会生成一个指向虚函数表的vptr指针
	playObj(&cc);
	playObj(&dd);

	system("pause");
	return 0;
}

子类的vptr指针的分步初始化

1、当执行父类的构造函数时,子类的vptr指针指向父类的虚函数表

2、当父类的构造函数运行完毕后,会把子类的vptr指针指向子类的虚函数表

多态时,注意子类和父类的步长不一样。

 

 

 

 

 

 

 

© 著作权归作者所有

共有 人打赏支持
沙米笔记
粉丝 28
博文 42
码字总数 45024
作品 0
深圳
程序员
JAVA多态的理解

面向对象的三大特性:封装、继承、多态,其中最难理解的就是多态 以下是网上某大神给的一个例子: 1.继承关系 class A { public String show(D obj){ return ("A and D"); } public String s...

小强零号 ⋅ 2015/09/23 ⋅ 0

Android源码设计模式解析与实战(一)

结合Android源码和图片加载的例子,介绍设计模式的同时,在例子中实际运用,更易于读者对设计模式的理解和使用。 本篇博客结合书中图片加载的例子和自己对知识点的理解,侧重记录下设计模式的...

xingjm8511 ⋅ 2016/12/19 ⋅ 0

24种设计模式学习记录第二篇

既然用了面向对象的程序设计语言,就要充分利用OO的三大特性:封装、继承、多态。大概说下这三个特性: 一.封装<数据保护> 从字面意思上可以理解把一些东西封装起来,这里要封装的东西就是所谓...

没有脚的大笨鸟 ⋅ 2014/03/30 ⋅ 0

Java编程思想 第8章 多态

1、Java语言的三大特性:继承、封装和多态。 继承:复用类的一种方法,可以简省很多代码; 封装:通过合并特征和行为来创建新的数据类型。【这种“数据类型”跟Java本身提供的8大“基本数据类...

木云凌 ⋅ 2016/02/23 ⋅ 0

Golang 学习笔记(5)—— 面向对象编程

本文为转载,原文:Golang 学习笔记(5)—— 面向对象编程 前言 golang是面向过程的语言,go中没有类,单go支持面向对象的编程,go中的struct就像其他语言中的类;go里没有继承,但可以通过...

ChainZhang ⋅ 2017/12/25 ⋅ 0

用C实现OOP面向对象编程(1)

如摘要所说,C语言不支持OOP(面向对象的编程)。并这不意味着我们就不能对C进行面向对象的开发,只是过程要复杂许多。原来以C++的许多工作,在C语言中需我们手动去完成。 博主将与大家一起研究...

临峰不畏 ⋅ 2015/12/26 ⋅ 0

对Java多态的理解

Java中多态性的实现 什么是多态 面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。 多态的定义:指允...

wf王帆 ⋅ 2016/05/22 ⋅ 0

C++灵魂所在之---多态的前世与今生

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

loving_forever_ ⋅ 2016/06/13 ⋅ 0

谈谈你对面向对象的理解

Question:请你谈一下面向对象? Answer: 面向对象是相对于面向过程而言的。面向过程语言是一种基于功能分析的、以算法为中心的程序设计方法;而面向对象是一种基于结构分析的、以数据为中心...

DevShaw ⋅ 2016/01/12 ⋅ 0

Python - 面向对象编程 - 初级篇

一、概述 1、 面向过程编程 面向过程编程往往用一长段代码来实现指定功能,在开发过程中最常见的操作就是复制粘贴,即:将之前实现的代码块复制到现需功能处。 2、 函数式编程 将具有相同功能...

MyPy ⋅ 2016/11/06 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

两道面试题,带你解析Java类加载机制

在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Grandpa{ static { System.out.println("爷爷在静态代码块"); }} cl...

1527 ⋅ 17分钟前 ⋅ 0

SpringCloud(Data Flow)

dataflow-server

赵-猛 ⋅ 27分钟前 ⋅ 0

深入理解Java虚拟机

这本书我读到第8章,之后就是在读不下去了。 读到后面是一种痛苦的体验,太多的东西是不全面的,大量的专有名词是没有解释的,读到最后很多东西仅仅是一个侧面,所以我觉得,这本书不适合初学...

颖伙虫 ⋅ 33分钟前 ⋅ 0

B树和B+树的总结

B树 为什么要B树 磁盘中有两个机械运动的部分,分别是盘片旋转和磁臂移动。盘片旋转就是我们市面上所提到的多少转每分钟,而磁盘移动则是在盘片旋转到指定位置以后,移动磁臂后开始进行数据的...

浮躁的码农 ⋅ 36分钟前 ⋅ 0

NanoPi NEO core/ Ubuntu16.04单网卡配置3个IP地址(2个静态,1个动态)

配置 root@NanoPi-NEO-Core:/etc/network# cat interfacesauto loiface lo inet loopbackallow-hotplug eth0iface eth0 inet static address 172.31.188.249 netmask 255.......

SamXIAO ⋅ 今天 ⋅ 0

三步为你的App集成LivePhoto功能

摘要:LivePhoto是iOS9新推出的一种拍照方式,类似于拍摄Gif图或录制视频片段生成图片。如果没有画面感,可以联想《哈利波特》霍格沃茨城堡的壁画,哈哈,很炫酷有木有,但坑爹的是只有iphone6S以...

壹峰 ⋅ 今天 ⋅ 0

centos7 git安装

由于centos中的源仓库中git不是最新版本,需要进行源码安装。 1、查看yum仓库git信息 [root@iZm5e3d4r5i5ml889vh6esZ zh]# yum info gitLoaded plugins: fastestmirrorLoading mirror s...

xixingzhe ⋅ 今天 ⋅ 0

input file 重复上传同一张图片失效的解决办法

解决办法 方法一:来回切换input[type='file']的type属性值,可以是‘text’,'button','button'....,然后再切换回来‘file’ 方法二:每次取消图片预览后,重置input[type='file']的value的...

时刻在奔跑 ⋅ 今天 ⋅ 0

Mahout推荐算法API详解

前言 用Mahout来构建推荐系统,是一件既简单又困难的事情。简单是因为Mahout完整地封装了“协同过滤”算法,并实现了并行化,提供非常简单的API接口;困难是因为我们不了解算法细节,很难去根...

xiaomin0322 ⋅ 今天 ⋅ 0

WampServer默认web服务器根目录位置

安装WampServer之后的web服务器根目录默认位置在WampServer安装目录下的www:

临江仙卜算子 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部