文档章节

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

沙米笔记
 沙米笔记
发布于 2016/05/08 16:21
字数 1647
阅读 352
收藏 9

面向对象的三大特性

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指针指向子类的虚函数表

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

 

 

 

 

 

 

 

© 著作权归作者所有

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

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

小强零号
2015/09/23
482
0
Android源码设计模式解析与实战(一)

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

xingjm8511
2016/12/19
278
0
基于C++的纯面向对象的通用高性能大并发TCP-SERVER/CLIENT开发框架实践系列之前言篇

基于C++的纯面向对象的通用高性能大并发TCP-SERVER/CLIENT开发框架实践系列之前言篇 yijian 2008-12-21 technologier@126.com 1. 回首 工作几年了,没什么沉淀,不是忙工作就是忙着休息,大四...

一见蓝天
2008/12/21
0
0
Java编程思想 第8章 多态

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

木云凌
2016/02/23
33
0
Golang 学习笔记(5)—— 面向对象编程

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

ChainZhang
2017/12/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

微服务分布式事务实现

https://www.processon.com/view/link/5b2144d7e4b001a14d3d2d30

WALK_MAN
今天
2
0
《大漠烟尘》读书笔记及读后感文章3700字

《大漠烟尘》读书笔记及读后感文章3700字: 在这个浮躁的社会里,你有多久没有好好读完一本书了? 我们总觉得自己和别人不一样,所以当看到别人身上的问题时,很少有“反求诸己”,反思自己。...

原创小博客
今天
3
0
大数据教程(9.5)用MR实现sql中的jion逻辑

上一篇博客讲解了使用jar -jar的方式来运行提交MR程序,以及通过修改YarnRunner的源码来实现MR的windows开发环境提交到集群的方式。本篇博主将分享sql中常见的join操作。 一、需求 订单数据表...

em_aaron
今天
3
0
十万个为什么之什么是resultful规范

起源 越来越多的人开始意识到,网站即软件,而且是一种新型的软件。这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency)、高并发等特点...

尾生
今天
3
0
Terraform配置文件(Terraform configuration)

Terraform配置文件 翻译自Terraform Configuration Terraform用文本文件来描述设备、设置变量。这些文件被称为Terraform配置文件,以.tf结尾。这一部分将讲述Terraform配置文件的加载与格式。...

buddie
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部