主页
  • 主页
  • 分类
  • 热文
  • 教程
  • 面试
  • 标签
C++

C++ 基础

C++ 主页
C++ 概述
C++ 环境
C++ 基本语法
C++ 注释
C++ 数据类型
C++ Hello, World
C++ 省略命名空间
C++ 数值类型
C++ 字符类型
C++ 布尔类型
C++ 变量
C++ 作用域
C++ 多个变量
C++ 输入输出基础
C++ 常量/文字
C++ 修饰符类型
C++ 存储类别
C++ 操作符
C++ 决策结构
C++ 循环结构
C++ foreach 循环
C++ 数字
C++ 数组
C++ 指针
C++ 枚举类型
C++ 引用变量
C++ 日期与时间
C++ 结构体
C++ 联合类型

C++ 字符串

C++ 字符串
C++ 字符串长度
C++ 字符串连接

C++ 函数

C++ 函数
C++ 多参数函数
C++ 递归
C++ return 语句
C++ 函数重载
C++ 函数重写

C++ 面向对象

C++ 面向对象
C++ 类和对象
C++ 多重继承
C++ 多层次继承
C++ 继承
C++ 重载
C++ 多态性
C++ 抽象
C++ 封装
C++ 接口

C++ 高级

C++ 文件和流
C++ 异常处理
C++ 动态内存
C++ 命名空间
C++ 模板
C++ 预处理器
C++ 信号量
C++ 多线程
C++ Web 编程
C++ 高级概念

基础

C++ 主页
C++ 概述
C++ 环境
C++ 基本语法
C++ 注释
C++ 数据类型
C++ Hello, World
C++ 省略命名空间
C++ 数值类型
C++ 字符类型
C++ 布尔类型
C++ 变量
C++ 作用域
C++ 多个变量
C++ 输入输出基础
C++ 常量/文字
C++ 修饰符类型
C++ 存储类别
C++ 操作符
C++ 决策结构
C++ 循环结构
C++ foreach 循环
C++ 数字
C++ 数组
C++ 指针
C++ 枚举类型
C++ 引用变量
C++ 日期与时间
C++ 结构体
C++ 联合类型

字符串

C++ 字符串
C++ 字符串长度
C++ 字符串连接

函数

C++ 函数
C++ 多参数函数
C++ 递归
C++ return 语句
C++ 函数重载
C++ 函数重写

面向对象

C++ 面向对象
C++ 类和对象
C++ 多重继承
C++ 多层次继承
C++ 继承
C++ 重载
C++ 多态性
C++ 抽象
C++ 封装
C++ 接口

高级

C++ 文件和流
C++ 异常处理
C++ 动态内存
C++ 命名空间
C++ 模板
C++ 预处理器
C++ 信号量
C++ 多线程
C++ Web 编程
C++ 高级概念

C++ 多态性


上一章 下一章

多态性(Polymorphism)意味着拥有多种形态。通常情况下,当存在一个类层次并且这些类通过继承相互关联时,就会发生多态性。

C++ 中的多态性意味着对成员函数的调用将导致不同的函数被执行,具体取决于调用该函数的对象类型。

示例:一个基类被另外两个类继承

#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 :" << width * height << endl;
         return width * height;
      }
};

class Rectangle: public Shape {
   public:
      Rectangle(int a = 0, int b = 0):Shape(a, b) { }

      int area () { 
         cout << "Rectangle class area :" << width * height << 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 :" << (width * height)/2 << endl;
         return (width * height / 2); 
      }
};

// 主函数
int main() {
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);

   // 存储 Rectangle 的地址
   shape = &rec;

   // 调用矩形区域
   shape->area();

   // 存储 Triangle 的地址
   shape = &tri;

   // 调用三角形区域
   shape->area();

   return 0;
}

当上述代码被编译和执行时,产生的结果如下:

Parent class area :70
Parent class area :50

输出错误的原因是函数 area() 的调用被编译器设置为基类中定义的版本。这是静态解析函数调用,或称为静态链接——函数调用在程序执行前就已经固定了。这也有时被称为早期绑定,因为 area() 函数在程序编译期间就已确定。

现在,让我们稍微修改一下程序,在 Shape 类中 area() 函数声明前加上关键字 virtual,使其看起来像这样:

#include <iostream>
using namespace std;

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 :" << width * height << endl;
         return width * height;
      }
};

class Rectangle: public Shape {
   public:
      Rectangle(int a = 0, int b = 0):Shape(a, b) { }

      int area () { 
         cout << "Rectangle class area :" << width * height << 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 :" << (width * height)/2 << endl;
         return (width * height / 2);
      }
};

// 主函数
int main() {
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);

   // 存储 Rectangle 的地址
   shape = &rec;

   // 调用矩形区域
   shape->area();

   // 存储 Triangle 的地址
   shape = &tri;

   // 调用三角形区域
   shape->area();

   return 0;
}

经过这个小小的改动后,当之前的示例代码被编译和执行时,产生的结果如下:

Rectangle class area :70
Triangle class area :25

这次,编译器查看指针的内容而不是它的类型。因此,由于 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;
      }
      
      // 纯虚函数
      virtual int area() = 0;
};

= 0 告诉编译器函数没有主体,上述虚函数将被称为纯虚函数。

上一章 下一章
阅读号二维码

关注阅读号

联系二维码

联系我们

© 2024 Yoagoa. All rights reserved.

粤ICP备18007391号

站点地图