首页 > 编程语言 >C++ 多态

C++ 多态

时间:2024-03-02 22:12:00浏览次数:24  
标签:函数 area int 多态 C++ Shape class

原文

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

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

 1 #include <iostream> 
 2 using namespace std;
 3 class Shape {
 4    protected:
 5       int width, height;
 6    public:
 7       Shape( int a=0, int b=0)
 8       {
 9          width = a;
10          height = b;
11       }
12       int area()
13       {
14          cout << "Parent class area :" <<endl;
15          return 0;
16       }
17 };
18 class Rectangle: public Shape{
19    public:
20       Rectangle( int a=0, int b=0):Shape(a, b) { }
21       int area ()
22       { 
23          cout << "Rectangle class area :" <<endl;
24          return (width * height); 
25       }
26 };
27 class Triangle: public Shape{
28    public:
29       Triangle( int a=0, int b=0):Shape(a, b) { }
30       int area ()
31       { 
32          cout << "Triangle class area :" <<endl;
33          return (width * height / 2); 
34       }
35 };
36 // 程序的主函数
37 int main( )
38 {
39    Shape *shape;
40    Rectangle rec(10,7);
41    Triangle  tri(10,5);
42    // 存储矩形的地址
43    shape = &rec;
44    // 调用矩形的求面积函数 area
45    shape->area();
46    // 存储三角形的地址
47    shape = &tri;
48    // 调用三角形的求面积函数 area
49    shape->area();
50    return 0;
51 }

结果

Parent class area :
Parent class area :

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

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

 1 class Shape {
 2    protected:
 3       int width, height;
 4    public:
 5       Shape( int a=0, int b=0)
 6       {
 7          width = a;
 8          height = b;
 9       }
10       virtual int area()
11       {
12          cout << "Parent class area :" <<endl;
13          return 0;
14       }
15 };

结果

Rectangle class area :
Triangle class area :

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

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

虚函数

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

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

纯虚函数

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

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

 1 class Shape {
 2    protected:
 3       int width, height;
 4    public:
 5       Shape( int a=0, int b=0)
 6       {
 7          width = a;
 8          height = b;
 9       }
10       // pure virtual function
11       virtual int area() = 0;    //= 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数12 };

 

标签:函数,area,int,多态,C++,Shape,class
From: https://www.cnblogs.com/uacs2024/p/18049356

相关文章

  • C++第七节课 new开辟空间 delete释放空间
    #include<iostream>usingnamespacestd;//C中开辟空间的方式所有的返回值都是void*///int*p=(int*)malloc(sizeof(int))///malloc在堆上开辟空间并没有进行初始化//////int*pa=(int*)calloc(1,sizeof(int));///calloc在堆上开辟空间是有初始化的......
  • C++ 输入/输出运算符重载
    C++能够使用流提取运算符>>和流插入运算符<<来输入和输出内置的数据类型。您可以重载流提取运算符和流插入运算符来操作对象等用户自定义的数据类型。在这里,有一点很重要,我们需要把运算符重载函数声明为类的友元函数,这样我们就能不用创建对象而直接调用函数。下面的实例演......
  • 随笔记录篇——C++iostream库 以及std
    这篇文章非原创,来自我学习过程中看到的其他博主发的一些资料,解决了我的疑问,在此进行整理。C语言的标准输入输出库是stdio.h库,是一个函数库,而不是类库。其中包含了我们其中所用的scanfpringf都是一些独立的全局函数,因为C语言是不支持类的。C++的标准输入输出库iostream是一个类......
  • C++ 关系运算符重载
    C++语言支持各种关系运算符(<、>、<=、>=、==等等),它们可用于比较C++内置的数据类型。您可以重载任何一个关系运算符,重载后的关系运算符可用于比较类的对象。1#include<iostream>2usingnamespacestd;3 4classDistance5{6  private:7 ......
  • C++ 一元运算符重载
    一元运算符只对一个操作数进行操作,下面是一元运算符的实例:递增运算符(++)和递减运算符(--)一元减运算符,即负号(-)逻辑非运算符(!)一元运算符通常出现在它们所操作的对象的左边,比如!obj、-obj和++obj,但有时它们也可以作为后缀,比如obj++或obj--。下面的实例演示了如何......
  • C++第六节课 引用变量 指针的升级版
    #include<iostream>usingnamespacestd;//C++的引用是C指针的升级可以提高代码的稳定性和健壮性//const修饰的引用是常引用//函数传参实参向形参进行传递默认是值的传递这个是值的一个副本两个互不影响intadd(constint&a,constint&b){///a++;避......
  • C++ 重载运算符和重载函数 二元运算符重载
    C++允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型......
  • c++多线程按行读取同一个每行长度不规则文件
    对于非常大的比如上百G的大文件读取,单线程读是非常非常慢的,需要考虑用多线程读,多个线程读同一个文件时不用加锁的,每个线程打开一个独立的文件句柄多线程读同一个文件实现思路思路1先打开一个文件句柄,获取整个文件大小file_size确定要采用线程读取的部分大小read_size和......
  • c++多线程编程
    c++线程库:<thread>创建线程:需要可调用的函数或者函数对象作为线程入口点例:std::threadthreadname(function_name,args...)在C++中,当使用std::thread创建线程并传递类的成员函数时,需要使用&来获取成员函数的地址,同时还需要传递对象的指针(或引用)作为第一个参数。......
  • C++ 继承
    1//基类2classAnimal{3  //eat()函数4  //sleep()函数5};678//派生类9classDog:publicAnimal{10  //bark()函数11};基类&派生类一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我......