什么是接口
arduino
我定义了一个类对象,这个类的public公共函数,就是接口;而private私有函数,就不是接口。
我实现了一个动态库,动态库开放出来的函数,就是接口;而动态库封装到实现内部的函数,就不是接口。
我写了一个程序A,想给另一个同事B使用,我们之间就要约定好接口。这个接口就是我给他提供什么公共函数,给他提供什么样子的数据结构体,这些都是接口。
在QT中,会有信号槽的概念,信号,也是接口;公共槽函数,也是接口;私有槽函数,就不是接口。
接口的工程意义
- 动态库的.h头文件就是接口
- 我给别人提供的函数声明是接口
- QT的信号是接口:"我告诉你我什么时候会发出什么信号"
封装:把复杂装进"黑盒子"
封装的本质就是造黑盒子:把复杂的内部实现藏起来,只是暴露简单的使用接口。
- 可以封装为函数:实现特定功能的函数接口
- 封装为类:合理抽象出来的类
- 封装为模块:实现复杂功能集合的功能模块,供他人使用
- 封装为dll:封装为动态库,基于头文件供他人使用
判断封装的好坏:高内聚,松耦合 高内聚:一个模块内部联系紧密 松耦合:模块之间依赖简单清晰
继承
继承的本质是代码复用和概念分层。 继承的工程价值:
- 代码复用:公共功能在基类实现一次
- 概念抽象:不同相机都是"一种相机"
- 扩展方便:新相机类型只需要实现差异部分



多态:同一接口,千变万化
多态就是"一个接口,多种实现",让代码具备运行时灵活性。
arduino
多态按字面的意思就是多种形态。
当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
在 C++ 中,多态(Polymorphism)是面向对象编程的重要特性之一。
C++ 多态允许使用基类指针或引用来调用子类的重写方法,从而使得同一接口可以表现不同的行为。
多态使得代码更加灵活和通用,程序可以通过基类指针或引用来操作不同类型的对象,而不需要显式区分对象类型。这样可以使代码更具扩展性,在增加新的形状类时不需要修改主程序。
以下是多态的几个关键点:
虚函数(Virtual Functions):
在基类中声明一个函数为虚函数,使用关键字virtual。
派生类可以重写(override)这个虚函数。
调用虚函数时,会根据对象的实际类型来决定调用哪个版本的函数。
动态绑定(Dynamic Binding):
也称为晚期绑定(Late Binding),在运行时确定函数调用的具体实现。
需要使用指向基类的指针或引用来调用虚函数,编译器在运行时根据对象的实际类型来决定调用哪个函数。
纯虚函数(Pure Virtual Functions):
一个包含纯虚函数的类被称为抽象类(Abstract Class),它不能被直接实例化。
纯虚函数没有函数体,声明时使用= 0。
它强制派生类提供具体的实现。
多态的实现机制:
虚函数表(V-Table):C++运行时使用虚函数表来实现多态。每个包含虚函数的类都有一个虚函数表,表中存储了指向类中所有虚函数的指针。
虚函数指针(V-Ptr):对象中包含一个指向该类虚函数表的指针。
哈哈哈哈
arduino
#include <iostream>
using namespace std;
// 基类 Animal
class Animal {
public:
// 虚函数 sound,为不同的动物发声提供接口
virtual void sound() const {
cout << "Animal makes a sound" << endl;
}
// 虚析构函数确保子类对象被正确析构
virtual ~Animal() {
cout << "Animal destroyed" << endl;
}
};
// 派生类 Dog,继承自 Animal
class Dog : public Animal {
public:
// 重写 sound 方法
void sound() const override {
cout << "Dog barks" << endl;
}
~Dog() {
cout << "Dog destroyed" << endl;
}
};
// 派生类 Cat,继承自 Animal
class Cat : public Animal {
public:
// 重写 sound 方法
void sound() const override {
cout << "Cat meows" << endl;
}
~Cat() {
cout << "Cat destroyed" << endl;
}
};
// 测试多态
int main() {
Animal* animalPtr; // 基类指针
// 创建 Dog 对象,并指向 Animal 指针
animalPtr = new Dog();
animalPtr->sound(); // 调用 Dog 的 sound 方法
delete animalPtr; // 释放内存,调用 Dog 和 Animal 的析构函数
// 创建 Cat 对象,并指向 Animal 指针
animalPtr = new Cat();
animalPtr->sound(); // 调用 Cat 的 sound 方法
delete animalPtr; // 释放内存,调用 Cat 和 Animal 的析构函数
return 0;
}
运行结果:

virtual 关键字:多态的开关
总结:面向对象的工程思维
- 接口:定义"怎么用",隐藏"怎么实现"
- 封装:制造"黑盒子",管理复杂度
- 继承:建立"是什么"关系,复用代码
- 多态:实现"一个接口,多种行为"