目录
多态的基本概念
如何实现多态
在C++中,派生类对象可以被当作基类对象使用
编程示例
关键概念总结
抽象类
一、抽象类的定义
基本语法
二、抽象类的核心特性
1. 不能直接实例化
2. 派生类必须实现所有纯虚函数才能成为具体类
3. 可以包含普通成员函数和数据成员
编程示例
关键点说明
接口
接口的基本概念
多态的基本概念
想象一下,你有一个遥控器(这就像是一个基类的指针),这个遥控器可以控制不同的电子设备(这些设备就像是派生类)。无论是电视、音响还是灯光,遥控器上的“开/关”按钮(这个按钮就像是一个虚函数)都能控制它们,但具体的操作(打开电视、播放音乐、开灯)则取决于你指向的设备。
如何实现多态
1. 使用虚函数(Virtual Function):
我们在基类中定义一个虚函数,这个函数可以在任何派生类中被“重写”或者说“定制”。使用关键字 virtual 来声明。
2. 创建派生类并重写虚函数:
在派生类中,我们提供该虚函数的具体实现。这就像是告诉遥控器,“当你控制我的这个设备时,这个按钮应该这样工作”。
3. 通过基类的引用或指针调用虚函数:
当我们使用基类类型的指针或引用来调用虚函数时,实际调用的是对象的实际类型(派生类)中的函数版本。
当基类包含至少一个虚函数(通常是纯虚函数),派生类重写该函数后,在main函数中用基类指针指向派生类对象,并通过该指针调用虚函数时,实际调用的是派生类的实现,这种现象称为多态。
在C++中,派生类对象可以被当作基类对象使用
-
派生类对象可以直接赋值给基类指针/引用
-
但反过来不行(基类对象不能当作派生类对象)
编程示例
#include <iostream>
using namespace std;
// 基类——遥控器(抽象概念)
class RemoteCon
{
public:
// 虚函数:声明遥控器的"开启"功能,允许子类重写
virtual void open() = 0; // 纯虚函数(=0表示没有默认实现)
// 这样RemoteCon就成为抽象类,不能直接实例化
};
// 派生类——电视遥控器,继承于基类遥控器
class TVRemoteCon : public RemoteCon
{
public:
// 重写(override)基类的open函数
void open() override
{
cout << "电视遥控器开启键被按下" << endl;
}
};
// 派生类——灯光遥控器,继承于基类遥控器
class LightRemoteCon : public RemoteCon
{
public:
void open() override
{
cout << "灯光遥控器开启键被按下" << endl;
}
};
// 派生类——空调遥控器,继承于基类遥控器
class AirConditionerRemoteCon : public RemoteCon
{
public:
void open() override
{
cout << "空调遥控器开启键被按下" << endl;
}
};
int main()
{
// 第一部分:通过指针实现多态
// 创建一个指向电视遥控器的基类指针
RemoteCon* remoteCon = new TVRemoteCon();
remoteCon->open(); // 调用TVRemoteCon的open()
// 创建一个指向灯光遥控器的基类指针
RemoteCon* remoteCon2 = new LightRemoteCon();
remoteCon2->open(); // 调用LightRemoteCon的open()
// 第二部分:通过引用实现多态
AirConditionerRemoteCon kongTiao; // 创建空调遥控器对象
RemoteCon& remoteCon3 = kongTiao; // 创建基类引用绑定到派生类对象
remoteCon3.open(); // 调用AirConditionerRemoteCon的open()
// 释放动态分配的内存
delete remoteCon;
delete remoteCon2;
return 0;
}
代码解释:
RemoteCon *remoteCon = new TVRemoteCon; // 创建一个指向电视的遥控器指针
remoteCon->open();
尽管 remoteCon
是 RemoteCon*
类型的指针,但它实际指向的是 TVRemoteCon
对象。在运行时,C++ 的多态机制会依据对象的实际类型来调用相应的 open
函数实现,所以这里调用的是 TVRemoteCon
类中的 open
函数。
关键概念总结
-
虚函数(virtual):允许函数在派生类中被重写
-
override关键字:明确表示重写基类虚函数
-
多态两种实现:
-
基类指针指向派生类对象
-
基类引用绑定派生类对象
-
-
运行时绑定:具体调用哪个函数在运行时决定
抽象类
一、抽象类的定义
抽象类是指包含至少一个纯虚函数的类,它不能被实例化,只能作为其他类的基类。
基本语法
class 抽象类名 {
public:
virtual 返回类型 函数名(参数列表) = 0; // 纯虚函数
// 其他成员...
};
二、抽象类的核心特性
1. 不能直接实例化
class Shape {
public:
virtual double area() = 0;
};
// Shape s; // 错误!不能创建抽象类对象
2. 派生类必须实现所有纯虚函数才能成为具体类
class Circle : public Shape {
public:
double area() override { return 3.14*r*r; } // 必须实现
};
3. 可以包含普通成员函数和数据成员
class Animal {
public:
virtual void speak() = 0;
void eat() { cout << "Eating..." << endl; } // 普通成员函数
protected:
int age; // 数据成员
};
编程示例
#include <iostream>
using namespace std;
// 这是一个抽象类,包含3个纯虚函数
// 因为有纯虚函数,所有这个类不能被实例化
class Teacher {
public:
virtual void course() = 0; // 声明课程内容的纯虚函数
virtual void startClass() = 0; // 开始上课的纯虚函数
virtual void endClass() = 0; // 结束课程的纯虚函数
};
// 具体派生类 EnglishTeacher
class EnglishTeacher : public Teacher {
public:
void course() override {
cout << "这节课是英语课" << endl;
}
void startClass() override {
cout << "开始上英语课" << endl;
}
void endClass() override {
cout << "英语课结束" << endl;
}
};
// 具体派生类 ProTeacher
class ProTeacher : public Teacher {
public:
void course() override {
cout << "这节课是C++" << endl;
}
void startClass() override {
cout << "开始上C++" << endl;
}
void endClass() override {
cout << "C++结束" << endl;
}
};
int main() {
// 直接使用具体类
EnglishTeacher t;
t.course(); // 输出: 这节课是英语课
t.startClass(); // 输出: 开始上英语课
t.endClass(); // 输出: 英语课结束
// 多态用法
Teacher* t2 = new ProTeacher;
t2->course(); // 输出: 这节课是C++
t2->startClass(); // 输出: 开始上C++
t2->endClass(); // 输出: C++结束
delete t2; // 记得释放内存
return 0;
}
关键点说明
-
多态的实现:
-
通过基类指针
Teacher*
指向派生类对象ProTeacher
-
调用虚函数时,实际执行的是派生类的实现
-
-
override关键字:
-
确保函数确实重写了基类的虚函数
-
如果签名不匹配,编译器会报错
-
-
抽象类的作用:
-
强制派生类实现特定接口
-
统一了不同种类教师的调用方式
-
-
内存管理:
-
示例中
new ProTeacher
需要手动delete
-
接口
在C++中,接口是一种特殊的抽象类,它只包含纯虚函数而不包含任何数据成员或具体实现。接口用于定义行为规范,让不同的类可以遵循相同的接口标准。
接口的基本概念
在 C++ 中,虽然没有像其他编程语言(比如 Java 中的接口Interface)一样直接定义接口的关键字,但可以通过抽象类和纯虚函数的方式来实现接口的概念。
接口通常用于定义类应该实现的方法,但不提供具体实现。这样的实现方式允许多个类共享相同的接口,同时让每个类根据需要去实现这些接口。
一个类作为接口可以通过以下步骤来实现:
1. 定义抽象类:创建一个包含纯虚函数的抽象类,这些函数构成了接口的一部分。这些函数在抽象类中只有声明而没有具体的实现。
2. 派生类实现接口:派生类继承抽象类,并实现其中的纯虚函数,以具体实现接口定义的方法。
#include <iostream>
using namespace std;
class Person // 接口
{
public:
virtual void eat() = 0; // 吃
virtual void drink() = 0; // 喝
virtual void haveFun() = 0; // 玩乐
};
class Woman : public Person
{
public:
void eat() override
{
cout << "麻辣鸡腿堡" << endl;
}
void drink() override
{
cout << "珍珠奶茶" << endl;
}
void haveFun() override
{
cout << "剧本杀" << endl;
}
};
class Man : public Person
{
public:
void eat() override
{
cout << "板烧鸡腿堡" << endl;
}
void drink() override
{
cout << "可乐" << endl;
}
void haveFun() override
{
cout << "打桌球" << endl;
}
};
int main()
{
Woman w;
w.eat();
w.drink();
w.haveFun();
Man m;
m.eat();
m.drink();
m.haveFun();
return 0;
}
Person
类是一个抽象基类,它包含了三个纯虚函数(eat()
, drink()
, haveFun()
),这实际上起到了接口的作用。
Woman
和 Man
类继承自 Person
并实现了所有这些纯虚函数。
所以可以说这是一个接口的实现,但更准确的说法是:
-
这是一个使用 C++ 纯虚函数实现的接口设计模式
-
Person
类扮演了接口的角色 -
Woman
和Man
是具体实现这个接口的类
在 C++ 中,这种设计常被称为"接口类"或"抽象基类",它强制派生类必须实现这些方法,这正是接口的核心特性。