C++ 多态/抽象类/接口类

C++ 多态/抽象类/接口类

一、C++ 多态

1.1 C++多态概述

  • C++的**多态(Polymorphism)是面向对象编程(OOP)的核心特性之一,允许在运行时通过统一的接口调用不同派生类的函数,从而实现“同一接口,不同表现”**的能力。
  • 多态分为两种:静态多态动态多态
  • 静态多态也叫早绑定,是在编译时就确定调用哪个函数的行。
  • 动态多态也叫晚绑定,在运行时根据对象的实际类型决定调用哪个函数,是通过**虚函数(virtual function)**实现的。

想象一下,你有一个遥控器(这就像是一个基类的指针),这个遥控器可以控制不同的电子设备(这些设备就像是派生类)。无论是电视、音响还是灯光,遥控器上的“开/关”按钮(这个按钮就像是一个虚函数)都能控制它们,但具体的操作(打开电视、播放音乐、开灯)则取决于你指向的设备。


1.2 如何实现多态

  1. 使用虚函数(Virtual Function)

    • 我们在基类中定义一个虚函数,这个函数可以在任何派生类中被“重写”或者说“定制”。

    • 使用关键字 virtual 来声明。

  2. 创建派生类并重写虚函数

    • 在派生类中,我们提供该虚函数的具体实现。这就像是告诉遥控器,“当你控制我的这个设备时,这个按钮应该这样工作”。
  3. 通过基类的引用或指针调用虚函数

    • 当我们使用基类类型的指针或引用来调用虚函数时,实际调用的是对象的实际类型(派生类)中的函数版本。

1.3 多态示例

#include <iostream>

using namespace std;

/* 基类 遥控器类 */
class RemoteCon{
public:
    virtual void openFunc(){                    // virtual 关键字使得该函数是一个虚函数,支持动态绑定(运行时绑定)
        cout << "遥控器的开被按下" << endl;
    }
};

/* 派生类 电视遥控器类 */
class TVRemoteCon : public RemoteCon{
public:
    void openFunc() override{                   // 派生类中虚函数的具体实现
        cout << "电视遥控器的开被按下" << endl;
    }
};

/* 派生类 音响遥控器类 */
class SoundRemoteCon : public RemoteCon{
public:
    void openFunc() override{                   // 派生类中虚函数的具体实现
        cout << "音响遥控器的开被按下" << endl;
    }
};

/* 派生类 灯光遥控器类 */
class LightRemoteCon : public RemoteCon{
public:
    void openFunc() override{                   // 派生类中虚函数的具体实现
        cout << "灯光遥控器的开被按下" << endl;
    }
};

/* 使用引用方式调用 */
void pressOpen(RemoteCon& remote)
{
    remote.openFunc();
}

int main()
{
    cout << "==========基类指针方式调用==========" << endl;

    RemoteCon *remoteCon1 = new TVRemoteCon;
    remoteCon1->openFunc();

    RemoteCon *remoteCon2 = new SoundRemoteCon;
    remoteCon2->openFunc();

    RemoteCon *remoteCon3 = new LightRemoteCon;
    remoteCon3->openFunc();

    cout << "==========基类引用方式调用==========" << endl;

    TVRemoteCon tv;
    SoundRemoteCon sound;
    LightRemoteCon light;

    pressOpen(tv);
    pressOpen(sound);
    pressOpen(light);

    return 0;
}

这段代码通过一个基类 RemoteCon 和三个派生类 TVRemoteConSoundRemoteConLightRemoteCon 演示了 C++ 中运行时多态的实现。基类中定义了一个虚函数 openFunc(),各个派生类分别重写该函数。在 main() 函数中,分别使用了基类指针基类引用两种方式调用虚函数,最终根据对象的实际类型,动态绑定到对应的函数实现上,输出不同的结果,体现了多态的核心特性——同一接口,不同行为

在这里插入图片描述


1.4 为什么使用多态

  • 灵活性:允许我们编写可以处理不确定类型的对象的代码。
  • 可扩展性:我们可以添加新的派生类而不必修改使用基类引用或指针的代码。
  • 接口与实现分离:我们可以设计一个稳定的接口,而将具体的实现留给派生类去处理。

二、C++ 抽象类

C++ 中的 抽象类(Abstract Class) 是一种不能实例化对象的类,它的主要作用是作为接口或基类,为派生类提供统一的函数接口规范。

2.1 什么是抽象类?

如果一个类中至少包含一个纯虚函数(pure virtual function),那么这个类就是抽象类

✅ 纯虚函数语法:

virtual 返回类型 函数名(参数列表) = 0;

这个 = 0 就表示函数没有实现,派生类必须重写(override)


2.2 抽象类的特点

  1. 包含至少一个纯虚函数

    • 抽象类至少有一个纯虚函数。这是一种特殊的虚函数,在抽象类中没有具体实现,而是留给派生类去实现。

    • 纯虚函数的声明方式是在函数声明的末尾加上 = 0 。

  2. 不能直接实例化

    • 由于抽象类不完整,所以不能直接创建它的对象。就像你不能直接使用“交通工具”的概念去任何地方,你需要一个具体的交通工具。
  3. 用于提供基础结构

    • 抽象类的主要目的是为派生类提供一个共同的基础结构,确保所有派生类都有一致的接口和行为。

2.3 抽象类示例一

#include <iostream>

using namespace std;

/* 抽象类 遥控器接口类 */
class RemoteCon{

public:
    virtual void openFunc() = 0;        // 纯虚函数:必须由派生类实现
};

/* 派生类 电视遥控器 */
class TVRemoteCon : public RemoteCon{

public:
    void openFunc() override{
        cout << "电视遥控器的开被按下" << endl;
    }
};

/* 派生类 音响遥控器 */
class SoundRemoteCon : public RemoteCon{

public:
    void openFunc() override{
        cout << "音响的遥控器开被按下" << endl;
    }
};

/* 派生类 灯光遥控器 */
class LightRemoteCon : public RemoteCon{

public:
    void openFunc() override{
        cout << "灯光的遥控器开被按下" << endl;
    }
};

/* 使用基类引用方式调用(体现多态) */
void pressOpen(RemoteCon& remote)
{
    remote.openFunc();
}

int main()
{
    cout << "==========基类指针方式调用(多态)==========" << endl;

    RemoteCon *remoteCon1 = new TVRemoteCon;
    RemoteCon *remoteCon2 = new SoundRemoteCon;
    RemoteCon *remoteCon3 = new LightRemoteCon;

    remoteCon1->openFunc();
    remoteCon2->openFunc();
    remoteCon3->openFunc();

    cout << "==========基类引用方式调用(多态)==========" << endl;

    TVRemoteCon tv;
    SoundRemoteCon sound;
    LightRemoteCon light;

    pressOpen(tv);
    pressOpen(sound);
    pressOpen(light);

    return 0;
}

这段代码演示了 C++ 中通过抽象类和虚函数实现多态的机制。基类 RemoteCon 定义了一个纯虚函数 openFunc(),因此它是一个抽象类,不能被直接实例化。三个派生类 TVRemoteConSoundRemoteConLightRemoteCon 分别继承自该抽象类,并实现了各自版本的 openFunc() 方法。main() 函数中分别使用了基类指针基类引用来调用这些派生类的 openFunc(),体现了运行时多态的特性:虽然通过统一的接口调用,但实际执行的是各个派生类各自实现的版本。这样设计使得代码更具扩展性和可维护性,是面向对象设计中“对接口编程”的典型范例。

在这里插入图片描述


2.4 抽象类示例二

#include <iostream>

using namespace std;

/* 基类 老师接口类 */
class Teacher{

public:
    string name;    // 名字
    string shool;   // 学校
    string major;   // 科目

    // 纯虚函数,必须由派生类实现
    virtual void goInClass() = 0;
    virtual void startTeaching() = 0;
    virtual void afterTeaching() = 0;
};

/* 派生类 英语老师 */
class EnglishTeacher : public Teacher{

public:
    void goInClass() override{
        cout << "英语老师进入教师" << endl;
    }
    void startTeaching() override{
        cout << "英语老师开始教学" << endl;
    }
    void afterTeaching() override{
        cout << "英语老师下课之后立马就回到了办公室" << endl;
    }
};

/* 派生类 编程老师 */
class ProTeacher : public Teacher{

public:
    void goInClass() override{
        cout << "编程老师进入机房" << endl;
    }
    void startTeaching() override{
        cout << "编程老师开始教学" << endl;
    }
    void afterTeaching() override{
        cout << "编程老师下课之后还教学生调代码" << endl;
    }
};

/* 派生类 电路老师 */
class CircuitTeacher : public Teacher{

public:
    void goInClass() override{
        cout << "电路老师进入实验室" << endl;
    }
    void startTeaching() override{
        cout << "电路老师开始教学" << endl;
    }
    void afterTeaching() override{
        cout << "电路老师下课之后还教学生画板子" << endl;
    }
};

/* 使用基类引用方式调用(体现多态) */
void teacherFunc(Teacher& teacher)
{
    teacher.goInClass();
    teacher.startTeaching();
    teacher.afterTeaching();
}

int main()
{
    cout << "==========对象实例方式调用==========(静态绑定)" << endl;
    EnglishTeacher e;
    e.goInClass();
    e.startTeaching();
    e.afterTeaching();
    cout << endl;

    cout << "==========基类指针方式调用==========(多态/动态绑定)" << endl;
    Teacher *teacher = new ProTeacher;
    teacher->goInClass();
    teacher->startTeaching();
    teacher->afterTeaching();
    cout << endl;

    cout << "==========基类引用方式调用==========(多态/动态绑定)" << endl;
    CircuitTeacher circuit;
    teacherFunc(circuit);
    cout << endl;

    return 0;
}

这段代码通过一个抽象基类 Teacher 和三个派生类 EnglishTeacherProTeacherCircuitTeacher,系统演示了 C++ 中的抽象类、纯虚函数和多态Teacher 类定义了三个纯虚函数,表示教师的上课流程,强制派生类必须实现这些函数,因此 Teacher 是一个抽象类,不能直接实例化。主函数中分别展示了三种调用方式:

  1. 对象实例调用(静态绑定)EnglishTeacher e; e.startTeaching();,在编译期就确定调用哪个函数,不支持多态;
  2. 基类指针调用(动态绑定):通过 Teacher* teacher = new ProTeacher; 访问虚函数,实现运行时多态;
  3. 基类引用调用(动态绑定):通过 teacherFunc(Teacher& teacher) 接口传入不同派生类对象,触发多态行为,调用对应类的重写函数。

整段代码体现了 C++ 中“接口编程、实现多态、提升扩展性”的设计思想。

在这里插入图片描述


三、C++ 接口类

在 C++ 中,**纯虚函数(pure virtual function)**和 接口类(interface class)是实现抽象和多态的重要机制,是面向对象编程中的核心概念之一。

3.1 什么是纯虚函数?

纯虚函数是在基类中声明但不提供实现,并要求所有派生类**必须重写(override)**的函数。

✅ 语法:

virtual void funcName() = 0;

这个 = 0 表示这是一个纯虚函数。


3.2 什么是接口类

在 C++ 中,一个类如果至少有一个纯虚函数,它就是一个抽象类,不能被实例化。如果一个类中所有成员函数都是纯虚函数,并且没有成员变量,我们称它为接口类

接口类就是一种只定义“功能规范”而不实现“具体逻辑”的类。相当于告诉派生类:“你必须提供自己的实现”。


3.3 接口类作用和意义

特性作用/好处
强制派生类实现保证所有子类都提供一致的功能实现
接口隔离便于代码解耦和模块划分
支持多态可以通过基类指针或引用调用派生类实现(运行时绑定)
实现面向接口编程避免依赖具体类,提高系统扩展性和可维护性

3.4 接口类实现步骤

一个类作为接口可以通过以下步骤来实现:

  1. 定义抽象类:创建一个包含纯虚函数的抽象类,这些函数构成了接口的一部分。这些函数在抽象类中只有声明而没有具体的实现。

  2. 派生类实现接口:派生类继承抽象类,并实现其中的纯虚函数,以具体实现接口定义的方法。


3.5 接口类示例

#include <iostream>

using namespace std;

/* 接口类 USB设备 */
class USBDevice{

public:
    virtual void connect() = 0;     // 纯虚函数,连接设备
    virtual void disconnect() = 0;  // 纯虚函数,断开设备

    virtual ~USBDevice(){};         // 虚析构函数
};

/* 派生类 U盘 */
class FlashDevice : public USBDevice{

public:
    void connect() override{
        cout << "U盘已连接!" << endl;
    }
    void disconnect() override{
        cout << "U盘已拔出!" << endl;
    }
};

/* 派生类 打印机 */
class Printer : public USBDevice{

public:
    void connect() override{
        cout << "打印机已连接!" << endl;
    }
    void disconnect() override{
        cout << "打印机已断开!" << endl;
    }
};

/* 多态调用函数 */
void useUSBDevice(USBDevice& device)
{
    device.connect();
    cout << "正在使用设备..." << endl;
    device.disconnect();
}

int main()
{
    FlashDevice fd;
    Printer pr;

    cout << "=== 使用 U盘 ===" << endl;
    useUSBDevice(fd);

    cout << "\n=== 使用 打印机 ===" << endl;
    useUSBDevice(pr);

    return 0;
}

这段代码展示了 C++ 中 抽象类(接口类)与多态 的应用。USBDevice 是一个接口类,里面定义了两个纯虚函数 connect()disconnect(),表示所有 USB 设备都必须具备的连接和断开功能。FlashDevice(U盘)和 Printer(打印机)类继承了这个接口,并各自实现了这两个功能。在 main() 函数中,通过一个名为 useUSBDevice() 的函数,使用接口类引用来调用具体设备的行为,体现了多态:即使用相同的接口,可以操作不同种类的 USB 设备,提升了代码的通用性和可扩展性。整体结构清晰,非常适合作为理解接口与多态的入门示例。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值