C++ 通过指针实现多态实例详解

yizhihongxing

C++ 通过指针实现多态实例详解

多态是面向对象编程语言的一个重要特性。在 C++ 中,实现多态的方法有虚函数和虚函数表、函数指针和指针数组、以及指针和引用等。其中,通过指针实现多态是一种常用的方式。在本篇文章中,我们将详细讲解如何通过指针实现多态。

什么是多态

多态是指不同的对象以不同的方式响应相同的消息的能力,这意味着不同的对象可以接受相同的消息,但是却可以表现出不同的行为。例如,在一个图形类中,不同的子类可以有不同的绘制方法,但是它们都可以接收“绘制”这个消息。

如何通过指针实现多态

在 C++ 中,通过指针实现多态的方法是将子类对象的指针赋值给父类对象的指针,并使用虚函数来调用方法。因为虚函数可以通过指针调用子类的方法,所以这样可以保证正确地调用不同子类的方法。

以下是通过指针实现多态的详细步骤:

  1. 定义基类和子类的结构体,并在基类中定义虚函数。
class Shape {
public:
    virtual void draw() { // 定义虚函数,使用 virtual 关键字
        std::cout << "This is a shape." << std::endl;
    }
};

class Circle : public Shape {
public:
    void draw() { // 重写虚函数
        std::cout << "This is a circle." << std::endl;
    }
};

class Rectangle : public Shape {
public:
    void draw() { // 重写虚函数
        std::cout << "This is a rectangle." << std::endl;
    }
};
  1. 在 main 函数中使用基类指针指向不同的子类对象。
int main() {
    Shape* shapes[2]; // 定义基类指针的数组
    Circle circle;
    Rectangle rectangle;
    shapes[0] = &circle; // 将子类对象的指针赋值给父类对象的指针
    shapes[1] = &rectangle;
    for (int i = 0; i < 2; ++i) {
        shapes[i]->draw(); // 调用虚函数
    }
    return 0;
}
  1. 编译运行程序,输出结果为:
This is a circle.
This is a rectangle.

这说明成功地实现了通过指针实现多态。

示例说明

示例 1

在这个示例中,我们通过指针实现了动物类和其两个子类,马和狗。每个子类都有一个不同的叫声函数。我们通过指针数组,将不同的子类对象指针赋值给基类对象指针,然后调用虚函数,从而实现了多态。

#include <iostream>

class Animal {
public:
    virtual void makeSound() { // 定义虚函数
        std::cout << "This is an animal." << std::endl;
    }
};

class Horse : public Animal {
public:
    void makeSound() { // 重写虚函数
        std::cout << "This is a horse. Neigh!" << std::endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() { // 重写虚函数
        std::cout << "This is a dog. Woof!" << std::endl;
    }
};

int main() {
    Animal* animals[2]; // 定义基类指针的数组
    Horse horse;
    Dog dog;
    animals[0] = &horse; // 将子类对象的指针赋值给父类对象的指针
    animals[1] = &dog;
    for (int i = 0; i < 2; ++i) {
        animals[i]->makeSound(); // 调用虚函数
    }
    return 0;
}

运行程序,输出结果为:

This is a horse. Neigh!
This is a dog. Woof!

示例 2

在这个示例中,我们通过指针实现了图形类和其两个子类,圆形和矩形。每个子类都有一个不同的绘制函数。我们通过指针数组,将不同的子类对象指针赋值给基类对象指针,然后调用虚函数,从而实现了多态。

#include <iostream>

class Shape {
public:
    virtual void draw() { // 定义虚函数
        std::cout << "This is a shape." << std::endl;
    }
};

class Circle : public Shape {
public:
    void draw() { // 重写虚函数
        std::cout << "This is a circle." << std::endl;
    }
};

class Rectangle : public Shape {
public:
    void draw() { // 重写虚函数
        std::cout << "This is a rectangle." << std::endl;
    }
};

int main() {
    Shape* shapes[2]; // 定义基类指针的数组
    Circle circle;
    Rectangle rectangle;
    shapes[0] = &circle; // 将子类对象的指针赋值给父类对象的指针
    shapes[1] = &rectangle;
    for (int i = 0; i < 2; ++i) {
        shapes[i]->draw(); // 调用虚函数
    }
    return 0;
}

运行程序,输出结果为:

This is a circle.
This is a rectangle.

结论

通过指针实现多态是 C++ 中一种常用的实现多态的方式。它让不同的子类对象以不同的方式响应相同的消息,从而实现了多态。在使用中要注意虚函数的定义和指针的使用,才能保证程序的正确性和可读性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ 通过指针实现多态实例详解 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • SpringBoot读写操作yml配置文件方法

    下面是SpringBoot读写操作yml配置文件方法的完整攻略。 1. yml配置文件基本语法 在SpringBoot中,我们通常使用yml配置文件来管理应用程序的配置信息。yml文件是以缩进的方式组织数据,具有可读性强、易于维护的特点。下面是一个简单的yml文件示例: server: port: 8080 spring: datasource: url: …

    other 2023年6月25日
    00
  • Linux(CentOS)常用操作指令(一)

    Linux(CentOS)常用操作指令(一) Introduction 在使用Linux(CentOS)操作系统时,我们经常需要使用到一些常用的指令,本篇文章将会介绍一些基础的操作指令,以供大家参考。 Command list 以下是一些常用的Linux(CentOS)操作指令: 1. cd cd指令是切换当前目录的命令。比如我们要进入”/home”目录,只…

    其他 2023年3月28日
    00
  • Android开发Activity的生命周期详解

    首先让我们来了解一下Android开发中Activity的生命周期。Activity是Android开发中最常用的组件之一,每个Activity都有自己的生命周期,这决定了Activity的创建、启动、运行、销毁等过程。了解Activity的生命周期可以更好地管理Activity的行为,如何响应用户交互和系统事件等。 生命周期概述 Activity的生命周期…

    other 2023年6月27日
    00
  • Go语言实现LRU算法的核心思想和实现过程

    Go语言实现LRU算法的核心思想和实现过程 简介 LRU (Least Recently Used)是一种常见的缓存淘汰策略,即当缓存空间已满时,把最近最少使用的元素先淘汰掉,以此来保证缓存空间的有效利用。本文将讲述如何使用Go语言来实现LRU算法的核心思想和实现过程。 核心思想 LRU算法的核心思想是基于链表+哈希表的组合实现。具体来说,我们可以维护一个双…

    other 2023年6月27日
    00
  • Go底层channel实现原理及示例详解

    Go底层channel实现原理及示例详解 介绍 Go是一门并发编程语言,其核心思想通过Goroutine和Channel实现轻量级并发。本文将详细讲解Go底层Channel实现原理,并提供两个示例说明。 Channel概述 Go中的Channel是一种实现同步、通信和控制Goroutine的途径,类似于Unix中的管道。它可以让不同的Goroutine之间进…

    other 2023年6月27日
    00
  • 一步一步跟我学易语言之自定义数据类型

    一步一步跟我学易语言之自定义数据类型 自定义数据类型是基于现有的数据类型创建的一种新的数据类型,它能够更好地满足业务需求。下面将介绍如何在易语言中创建自定义数据类型。 步骤1:声明结构体 结构体是存储复杂数据类型的一种方式,它由多个变量组成,并且这些变量的类型可以不同。声明结构体的语法如下: 类型 结构体名 { 类型1 变量1; 类型2 变量2; … 类…

    other 2023年6月25日
    00
  • Android startService的使用与Service生命周期案例详解

    Android中的Service是一种可以在后台运行的组件,可以执行长时间运行的任务或提供长时间运行的进程。startService方法可以启动一个Service,在Service运行之后,Service将被保持在后台,即使绑定Service的所有组件都被销毁,Service 仍将继续运行。 下面我们来详细讲解“Android startService的使用…

    other 2023年6月27日
    00
  • java中反射和注解的简单使用方法

    使用反射和注解是Java编程中的重要技术,允许Java程序动态地获取和操作应用程序运行时的信息。在本攻略中,我将详细解释如何在Java中使用反射和注解。 反射 反射的概念 反射是Java中一个强大的机制,它允许程序员在运行时获取一个类的信息(比如成员变量、方法和构造函数等),并且可以使用java.lang.reflect包实现在程序运行时调用这些信息所表示的…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部