C++:多态之虚函数

简介:             一个面向对象的系统常常要求一组具有相同基本语义的方法能在同一接口下为不同的对象服务,这就是多态性(polymorphism).           通俗的来说,多态就是在一个方法在不同基类的派生类中表现出不同的实现形式。
      

     一个面向对象的系统常常要求一组具有相同基本语义的方法能在同一接口下为不同的对象服务,这就是多态性(polymorphism).

          通俗的来说,多态就是在一个方法在不同基类的派生类中表现出不同的实现形式。比如,定义水果类为基类,苹果,梨,香蕉为派生类,在水果类,苹果,梨,香蕉中都有一个计算蒸发率的成员函数,但是,在苹果,梨,香蕉中,因为他们是不同水果,有不同蒸发率,所以,虽然同样是计算蒸发率,但是计算的方法不同,这种用不同方法计算不同派生类蒸发率的方式就是多态。

      在C++中,多态分为:编译时的多态性和运行时的多态性。其中,编译时的多态性通过重载和模板来实现,其实现的机制为一种静态绑定的机制;而运行时的多态性通过虚函数来实现,其实现的方式为一种动态绑定的方式。


    先来看一种静态绑定机制的多态:

   

#include<iostream>
using namespace std;

class People    //人类
{
public:
	print() {cout<<"我是人类"<<endl;}
};

class Singer:People   //歌手类
{
public:
	print() {cout<<"我是歌手:Jay!"<<endl;}
};

class Programmer:People  //程序猿类
{
public:
	print() {cout<<"我是一个程序猿:Vac!"<<endl;}
};


int main()
{
	People p;
	Singer Jay;   //歌手Jay
	Programmer Vac;  //程序猿Vac

	p.print();

	cout<<endl;

	Jay.print();

	cout<<endl;

	Vac.print();

	cout<<endl;

	return 0;


}

结果如我们所预料的那样:




Singer JayProgrammerVac分别调用本类中定义的print()函数,输出的结果也是我们想要的。但是这种调用是建立在静态绑定机制上的,不具备多态特征。


PS:

  多态调用是借助于指向基类的指针或引用的调用。


下面来看一下用指针访问的情况:


#include<iostream>
using namespace std;

class People    //人类
{
public:
	print() {cout<<"我是人类"<<endl;}
};


class Singer:public People   //歌手类
{
public:
	print() {cout<<"我是歌手:Jay!"<<endl;}
};

class Programmer:public People  //程序猿类
{
public:
	print() {cout<<"我是一个程序猿:Vac!"<<endl;}
};

int main()
{
	People p;
	Singer Jay;   //歌手Jay
	Programmer Vac;  //程序猿Vac

	People * Pp=&p;
	People * PJay=&Jay;
	People * PVac=&Vac;

        Pp->print();
	PJay->print();
	PVac->print();

	return 0;



}


运行时出现如下结果:




这显然不是我们想要得到的,指针所执行的函数都是基类的print()函数,根本没有实现多态。



解决方法:


   


只要在声明基类People的时候,将print()声明为虚函数,则在用指针或引用访问print()函数的时候,调用的是指针所指向的重定义的函数,而不是指向原来基类中的函数。


     总结虚函数:

             指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数






  
目录
相关文章
|
6月前
|
存储 人工智能 编译器
c++--多态
上一篇文章已经介绍了c++的继承,那么这篇文章将会介绍多态。看完多态的概念,你一定会感觉脑子雾蒙蒙的,那么我们先以举一个例子,来给这朦胧大致勾勒出一个画面,在此之前,先介绍一个名词虚函数,(要注意与虚拟继承区分)重定义: 重定义(隐藏)只要求函数名相同(但要符合重载的要求,其实两者实际上就是重载);重定义下:在这种情况下,如果通过父类指针或引用调用函数,会调用父类的函数而不是子类。重定义(或称为隐藏)发生的原因是因为函数名相同但参数列表不同,导致编译器无法确定调用哪一个版本的函数。
132 0
|
10月前
|
编译器 C++
c++中的多态
c++中的多态
|
9月前
|
存储 编译器 C++
【c++】多态(多态的概念及实现、虚函数重写、纯虚函数和抽象类、虚函数表、多态的实现过程)
本文介绍了面向对象编程中的多态特性,涵盖其概念、实现条件及原理。多态指“一个接口,多种实现”,通过基类指针或引用来调用不同派生类的重写虚函数,实现运行时多态。文中详细解释了虚函数、虚函数表(vtable)、纯虚函数与抽象类的概念,并通过代码示例展示了多态的具体应用。此外,还讨论了动态绑定和静态绑定的区别,帮助读者深入理解多态机制。最后总结了多态在编程中的重要性和应用场景。 文章结构清晰,从基础到深入,适合初学者和有一定基础的开发者学习。如果你觉得内容有帮助,请点赞支持。 ❤❤❤
1145 0
|
11月前
|
Serverless 编译器 C++
【C++面向对象——类的多态性与虚函数】计算图像面积(头歌实践教学平台习题)【合集】
本任务要求设计一个矩形类、圆形类和图形基类,计算并输出相应图形面积。相关知识点包括纯虚函数和抽象类的使用。 **目录:** - 任务描述 - 相关知识 - 纯虚函数 - 特点 - 使用场景 - 作用 - 注意事项 - 相关概念对比 - 抽象类的使用 - 定义与概念 - 使用场景 - 编程要求 - 测试说明 - 通关代码 - 测试结果 **任务概述:** 1. **图形基类(Shape)**:包含纯虚函数 `void PrintArea()`。 2. **矩形类(Rectangle)**:继承 Shape 类,重写 `Print
256 4
|
11月前
|
设计模式 IDE 编译器
【C++面向对象——类的多态性与虚函数】编写教学游戏:认识动物(头歌实践教学平台习题)【合集】
本项目旨在通过C++编程实现一个教学游戏,帮助小朋友认识动物。程序设计了一个动物园场景,包含Dog、Bird和Frog三种动物。每个动物都有move和shout行为,用于展示其特征。游戏随机挑选10个动物,前5个供学习,后5个用于测试。使用虚函数和多态实现不同动物的行为,确保代码灵活扩展。此外,通过typeid获取对象类型,并利用strstr辅助判断类型。相关头文件如&lt;string&gt;、&lt;cstdlib&gt;等确保程序正常运行。最终,根据小朋友的回答计算得分,提供互动学习体验。 - **任务描述**:编写教学游戏,随机挑选10个动物进行展示与测试。 - **类设计**:基类
217 3
|
编译器 C++
C++入门12——详解多态1
C++入门12——详解多态1
148 2
C++入门12——详解多态1
|
存储 编译器 数据安全/隐私保护
【C++】多态
多态是面向对象编程中的重要特性,允许通过基类引用调用派生类的具体方法,实现代码的灵活性和扩展性。其核心机制包括虚函数、动态绑定及继承。通过声明虚函数并让派生类重写这些函数,可以在运行时决定具体调用哪个版本的方法。此外,多态还涉及虚函数表(vtable)的使用,其中存储了虚函数的指针,确保调用正确的实现。为了防止资源泄露,基类的析构函数应声明为虚函数。多态的底层实现涉及对象内部的虚函数表指针,指向特定于类的虚函数表,支持动态方法解析。
145 1
|
C++
C++入门13——详解多态2
C++入门13——详解多态2
219 1
|
存储 编译器 C++
【C++】深度解剖多态(下)
【C++】深度解剖多态(下)
163 1
【C++】深度解剖多态(下)