在 C++ 中,接口(Interface) 是一种特殊的类,它只定义“做什么”(即函数声明),而不提供“怎么做”(即函数实现),其核心作用是规定类的行为规范,强制派生类实现特定功能,同时隐藏具体实现细节。

C++ 中没有专门的 interface 关键字,通常通过纯虚函数抽象类来模拟接口。

一、接口的定义:纯虚函数与抽象类

  • 纯虚函数:在基类中声明的、没有具体实现的虚函数,语法为 virtual 返回值类型 函数名(参数列表) = 0;
  • 抽象类:包含纯虚函数的类。抽象类不能实例化对象(无法创建具体实例),只能作为基类被其他类继承。

当一个类继承自抽象类时,必须重写所有纯虚函数(提供具体实现),否则该派生类仍为抽象类(也不能实例化)。

二、接口的示例:定义“可打印”接口

假设我们需要一个“可打印”的接口,要求所有实现该接口的类都必须提供“打印自身信息”的功能。

#include <iostream>
#include <string>
using namespace std;

// 接口类(抽象类):定义可打印的规范
class Printable {
public:
// 纯虚函数:仅声明,无实现,强制派生类实现
virtual void print() const = 0;

// 接口类可以有虚析构函数(避免派生类析构不被调用)
virtual ~Printable() {}
};

// 派生类1:实现 Printable 接口
class Person : public Printable {
private:
string name;
int age;
public:
Person(string n, int a) : name(n), age(a) {}

// 必须重写纯虚函数 print()
void print() const override {
cout << "Person: " << name << ", " << age << "岁" << endl;
}
};

// 派生类2:实现 Printable 接口
class Book : public Printable {
private:
string title;
string author;
public:
Book(string t, string a) : title(t), author(a) {}

// 必须重写纯虚函数 print()
void print() const override {
cout << "Book: 《" << title << "》,作者:" << author << endl;
}
};

// 通用函数:接收 Printable 接口类型,调用 print()
void printAll(const Printable* obj) {
obj->print(); // 多态调用:实际调用派生类的实现
}

int main() {
// 不能实例化接口类(抽象类)
// Printable p; // 错误:抽象类无法创建对象

// 创建实现接口的派生类对象
Printable* p1 = new Person("Alice", 20);
Printable* p2 = new Book("C++ Primer", "Stanley Lippman");

// 统一调用接口方法,实现多态
printAll(p1); // 输出:Person: Alice, 20岁
printAll(p2); // 输出:Book: 《C++ Primer》,作者:Stanley Lippman

delete p1;
delete p2;
return 0;
}

三、接口的核心特性

  1. 只定义规范,不提供实现:接口中的函数都是纯虚函数,没有具体代码,仅规定派生类必须实现哪些功能。
  2. 不能实例化:接口是抽象类,无法创建对象,只能作为基类被继承。
  3. 强制实现:派生类必须重写接口中的所有纯虚函数,否则自身仍为抽象类(无法实例化)。
  4. 多态基础:通过接口指针或引用,可以统一调用不同派生类的实现(如示例中 printAll 函数对 PersonBook 的统一处理)。
  5. 接口隔离:接口只包含与功能相关的函数,不包含成员变量(或仅包含常量),确保接口的简洁性。

四、接口的作用

  1. 规范行为:强制派生类遵循统一的行为标准(如“可打印”接口要求所有类必须实现 print 方法),保证代码的一致性。
  2. 解耦:接口将“功能定义”与“具体实现”分离。使用接口的代码只需关注接口本身,无需关心派生类的具体实现,降低代码耦合度。
  3. 扩展性:新增功能时,只需创建新的派生类实现接口,无需修改使用接口的现有代码(符合“开闭原则”)。例如,若新增 Car 类实现 Printable 接口,printAll 函数无需修改即可直接使用。
  4. 多态调用:通过接口实现多态,使同一接口能适配不同实现,提高代码的灵活性。