`
murongzilin
  • 浏览: 5300 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

c++多态性

c++ 
阅读更多


多态性可以简单的概括为一个接口,多种方法,程序在运行时才决定调用的函数,他是面向对象编程领域的核心概念。多态(polymorphisn),字面意思多种形态。

 

         c++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写(重写的话可以有两种,直接重写成员函数和重写虚函数,只有重写了虚函数才能算作是体现了c++多态性)。而重载则是允许有多个同名的函数,这些函数的参数列表不同,允许参数个数不同,参数类型不同,或者两者都不同。编辑器会根据这些函数的不同列表,将同名的函数的名称做修饰,从而生成一些不同名称的预处理函数,来实现同名函数调用时的重载问题(C++用名称压扎技术来改变函数名区分参数不同的同名函数。名称压扎是一系列代码被附加到函数名上以表决参数类型以及他们出现的次序,名称压扎对编程来说是看不到的,它在编译过程中悄悄进行,在连接过程默默使用,名称压扎不是C++标准,所以哥哥编译器的名称压扎方案可能不同)。但这并没有体现多态性。

 

         多态与非多态的实质区别就是函数地址是早绑定还是晚绑定。如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并产生代码,是静态的,就是说地址是早绑定的。而如果函数调用的地址不能再编译器期间确定,需要在运行时才确定,这就属于晚绑定。

 

         多态的作用是什么?封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是哪个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。

 

         最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。如果没有使用虚函数的话,即没有利用C++多态性,则利用基类指针调用相应的函数时候,将总被限制在基类函数本省,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,二固定的地址将始终调用到同一个函数,这就无法实现一个接口,多种方法的目的了。

 


#include <iostream.h>
class Animal
{
public:
	void eat(){
		cout << "animal eat" << endl;
	}

	void sleep(){
		cout << "animal sleep" << endl;
	}

	virtual void breathe(){
		cout << "animal breathe" << endl;
	}
};

class Fish : public Animal
{
public:
	void sleep(){
		cout << "fish sleep" << endl;
	}

	void breathe(){
		cout << "fish breathe" << endl;
	}
};

void main()
{
	Animal an;
	Fish fs;
	Animal *p = &an;
	p -> sleep();
	p -> breathe();
	p = &fs;
	p -> sleep();
	p -> breathe();
	Fish *p = (Fish *)&an;
	p -> sleep();
	p -> breathe();
}
animal sleep
animal breathe
animal sleep
fish breathe
fish sleep
animal breathe
 

  第一个p -> sleep()p -> breathe()都很好理解,本身是基类指针,指向的又是基类对象,调用的都是基类本身的函数,因此输出结果就是animal sleep animal breathe;

 

第二个输出结果是animal sleepfish breathep -> sleep()p -> breathe()则是基类指针执行子类对象,正是体现多态的用法,p->sleep()由于是个基类指针,指向是一个固定偏移量的函数,因此此时指向的就只能是基类的sleep()函数的代码了,因此输出的结果还是animal sleep。而p->breathe()指针是基类指针,指向的breathe()是一个虚函数,由于每个虚函数都有一个虚函数列表,此时,p调用breathe()并不是直接调用函数,而是通过虚函数列表找到相应的函数的地址,因此,根据指向的对象不同,函数的地址也将不同,这里将找到对应的子类的breathe()函数的地址,因此输出的结果也会是子类的结果fish breathe.

 

第三个输出结果是fish sleep和animal breathe,这是一个用字咧的指针去指向一个强制类型转换为子类的基类对象。结果,并不是很理解这种用法,从原理上来解释,由于B是子类指针,虽然被赋予了基类对象地址,但是p->sleep()在调用的时候,由于地址偏移量固定,偏移量是子类对象的偏移量,于是即使在指向了一个基类对象的情况下,还是调用到了子类的函数,虽然可能从始到终都没有子类对象的实例化出现。而p->breathe()的调用,可能还是因为C++多态性的原因,由于指向的是一个基类对象,通过虚函数列表的引用,找到了基类中breathe()函数的地址,因此调用了基类的函数。由此可见多态性的强大,可以适应各种变化,不论指针是基类的还是子类的,都能找到正确的实现方法(另一种理解:虚函数表指针是保存在类的实例中的,每个实例都有一个虚函数表指针,而一般的方法则和类的实例无关,函数表指针不保存在实例中,即使没有生成类的实例,一般方法的函数表仍然存在)。

分享到:
评论

相关推荐

    c++多态性与虚函数练习题

    1、理解多态性的概念。 2、熟练掌握虚函数的作用及其使用方法。 3、掌握静态关联和动态关联的概念和用法。 4、理解纯虚函数和抽象类的概念和用法。 (二)实验内容 1、定义一个类A,在A中有两个私有的整型变量a和b,...

    C++ 多态性

    关于c++多态性的讲解 对于初学c++者有用。。。

    c++多态性答案

    c++多态性与虚函数习题答案,这些复习资料供大家使用

    c++多态性和虚函数

    c++ 多态性 虚函数

    C++ 多态性 虚函数 各种例子

    C++ 多态性 虚函数 各种例子 自己写的 肯定运行成功

    C++实验报告多态性.doc

    面向对象程序设计及C++(多态性实验实验报告)

    c++多态性课件

    C++多态性 其中包含一部分代码及例子 如有错误请及时反馈 谢谢

    C++多态性实验报告

    (1)在《C++面向对象程序设计》第6章例6.3的基础上作以下修改,并作必要的讨论。 ○1把构造函数修改为带参数的函数,在建立对象初始化。 ○2先不将析构函数声明为virtual,在main函数中另设一个指向Circle类对象...

    C++多态性的相关资料

    C++多态性的样例程序由于事先对各种人的任务已作了规定,因此,在得到同一个消息时,各种人都知道自己应当怎么做(工作机制事先安排),这就是多态性。可以设想如果不利用多态性那么校长就要分别给学生、家长、教师...

    c++课件 多态性与虚函数

    c++课件 多态性与虚函数

    C++多态性与虚函数

    第9章 多态性与虚函数 本章学习要求: 虚函数 多态性 静态与动态联编 9.1 多态性的概念 9.2 虚函数 9.3 静态绑定与动态绑定 9.4 纯虚函数和抽象类

    c++多态性与虚函数

    主要简述了c++中的多态性,附上代码,详细简述了c++中的多态性,请好好看!

    C++中的多态性的分析与作用

    我这篇主要写了关于多态性的一些分析,描述了多态性的作用等等方面。

    C++中的多态性 多态性

    详细介绍了C++中的多态性,使读者对于C++中的多态性有深入的理解

    多态性实验

    (2)掌握双目运算符、单目运算符的重载方法,对常用算术运算符能在自定义类中通过友元函数、成员函数进行重载,以实现静态多态性。 (3)掌握通过继承、虚函数、基类的指针或引用实现动态多态性的方法。 (4)理解...

    关于C++多态性的一些结论

    c++中关于在虚函数或重载中构造函数、拷贝构造函数和析构函数在派生类和基类中的调用情况

    C++虚函数与多态性

    C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写。而重载则是允许有多个同名的函数,而这些函数的参数列表不同,允许参数个数不同,...

    C++中多态性的演示

    C++中多态性的的演示,本文档演示了c++中的多态性

    多态性实验报告-实验七

    课程名称《面向对象程序设计》实验项目:多态性;北京信息科技大学信安专业实验报告、实验七

    c++多态性相关习题.pdf

    .

Global site tag (gtag.js) - Google Analytics