首页 > 编程语言 >开心档之C++ 多态

开心档之C++ 多态

时间:2023-04-27 15:11:43浏览次数:52  
标签:开心 函数 area int 多态 C++ Shape 基类

C++ 多态

多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。

C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

下面的实例中,基类 Shape 被派生为两个类,如下所示:

实例

#include <iostream> 
using namespace std;
 
class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};
class Rectangle: public Shape{
   public:
      Rectangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Rectangle class area :" <<endl;
         return (width * height); 
      }
};
class Triangle: public Shape{
   public:
      Triangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Triangle class area :" <<endl;
         return (width * height / 2); 
      }
};
// 程序的主函数
int main( )
{
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);
 
   // 存储矩形的地址
   shape = &rec;
   // 调用矩形的求面积函数 area
   shape->area();
 
   // 存储三角形的地址
   shape = &tri;
   // 调用三角形的求面积函数 area
   shape->area();
   
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:


Parent class area :
Parent class area :

导致错误输出的原因是,调用函数 area() 被编译器设置为基类中的版本,这就是所谓的静态多态 ,或静态链接 - 函数调用在程序执行前就准备好了。有时候这也被称为早绑定,因为 area() 函数在程序编译期间就已经设置好了。

但现在,让我们对程序稍作修改,在 Shape 类中,area() 的声明前放置关键字 virtual,如下所示:

class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      virtual int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};

修改后,当编译和执行前面的实例代码时,它会产生以下结果:


Rectangle class area :
Triangle class area :

此时,编译器看的是指针的内容,而不是它的类型。因此,由于 tri 和 rec 类的对象的地址存储在 *shape 中,所以会调用各自的 area() 函数。

正如您所看到的,每个子类都有一个函数 area() 的独立实现。这就是多态的一般使用方式。有了多态,您可以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。

虚函数

虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。

我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接 ,或后期绑定。

纯虚函数

您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。

我们可以把基类中的虚函数 area() 改写如下:

class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      // pure virtual function
      virtual int area() = 0;
};

= 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数。

标签:开心,函数,area,int,多态,C++,Shape,基类
From: https://www.cnblogs.com/gddg/p/17358959.html

相关文章

  • 开心档之C++ 引用
    C++引用引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。C++引用vs指针引用很容易与指针混淆,它们之间有三个主要的不同:不存在空引用。引用必须连接到一块合法的内存。一旦引用被初始......
  • 开心档之C++ STL 教程
    C++STL教程在前面的章节中,我们已经学习了C++模板的概念。C++STL(标准模板库)是一套功能强大的C++模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量、链表、队列、栈。C++标准模板库的核心包括以下三个组件:组件描述容......
  • UNRAID6.11.1开心版下载及使用说明(集成中文插件)
    众所周知,所谓开心版就是已经解除限制功能,可正常开心使用。申明:此版本用于个人测试研究使用,如用于生产环境请购买官方正版,支持正版。部份资源转载于网络,请自行测试研究,下载测试后自行删除,如因软件版权及功能引起的任何问题自用户自行承担。该版本集成了常用插件,默认简体中文界面,......
  • c++打卡第十七天
    一、问题描述二、设计思路①、对于每个小孩得所得到的糖果数我们可以定义一个数组存储它们。②、需要进行循环结构,同时循环停止的条件为10个小孩得糖果数相同。③、小孩所得得糖果为奇数时需要向老师要一块后才再次分一半给后一个小朋友,这时候我们需要选择结构来实现。④、我们......
  • C++ linux epoll并发服务器模型初探
    socket通讯流程图最简单的可以通讯的C++服务器端代码:#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/socket.h>#include<arpa/inet.h>#include<netinet/in.h>#defineSERV_PORT8000intmain(void){intlfd......
  • 用C++编写一个简单的发布者和订阅者
    摘要:节点(Node)是通过ROS图进行通信的可执行进程。本文分享自华为云社区《编写一个简单的发布者和订阅者》,作者:MAVER1CK。@[toc]参考官方文档:Writingasimplepublisherandsubscriber(C++)背景节点(Node)是通过ROS图进行通信的可执行进程。在本教程中,节点将通过话题(To......
  • 基于C++的AI贪吃蛇
    访问【WRITE-BUG数字空间】_[内附完整源码和文档]用C++做了个有AI功能的贪吃蛇小游戏,希望大家enjoyit.总体概况开发环境:VIsualStudio2017开发语言:C++和少许WindowsAPI运行环境:Windows1001初始化工作-游戏设置游戏设置和相关初始化放在了一个类里面,并进行了静态声明。主要设......
  • 【C++】类与对象(上)
    系列文章之前的文章中讲解了,什么是类、类的实例化,以及封装的意义,若仍有不理解的部分可以移步上一篇文章  【C++】类与对象(引入)目录系列文章1.默认成员函数2.构造函数2.1定义2.2特性2.2.1重载构造函数2.2.2与缺省参数混合使用2.2.3默认构造函数3.析构函数3.1定义3.2特性4.拷贝构造......
  • c++输出格式控制
    c++输出格式控制 一.控制符需要<iomanip>头文件常用:1.保留几位有效数字:setpricision(),括号里是保留的位数2.保留几位小数:setiosflags(ios::fixed)<<setpricision(),括号里是保留的位数(注意前面半句会影响此后所有setpricision()的用法,都变成保留小数位数,不只是这......
  • 【C++】类与对象(引入)
    目录前言类的引入类的定义封装与访问限定符封装访问限定符类的实例化类的大小this指针特性前言......