C++ 接口
概述
在 C++ 中,接口是通过抽象类和纯虚函数来实现的。接口定义了一组方法,派生类必须实现这些方法。
抽象类
什么是抽象类
抽象类是包含至少一个纯虚函数的类。抽象类不能被实例化,只能被继承。
cpp
class Shape {
public:
// 纯虚函数
virtual double area() const = 0;
virtual double perimeter() const = 0;
// 虚析构函数
virtual ~Shape() = default;
// 普通成员函数
void printInfo() const {
std::cout << "Area: " << area() << std::endl;
std::cout << "Perimeter: " << perimeter() << std::endl;
}
};纯虚函数
纯虚函数是在基类中声明但没有实现的函数,必须在派生类中实现。
cpp
virtual void function() = 0;特点:
- 以
= 0结尾 - 没有函数体
- 使类成为抽象类
- 派生类必须实现它
接口实现
基本接口
cpp
#include <iostream>
#include <vector>
// 接口
class Printable {
public:
virtual void print() const = 0;
virtual ~Printable() = default;
};
// 实现
class Document : public Printable {
private:
std::string content;
public:
Document(const std::string& text) : content(text) {}
void print() const override {
std::cout << "Document: " << content << std::endl;
}
};
class Image : public Printable {
private:
std::string filename;
public:
Image(const std::string& file) : filename(file) {}
void print() const override {
std::cout << "Image: " << filename << std::endl;
}
};
int main() {
std::vector<Printable*> items;
items.push_back(new Document("Hello World"));
items.push_back(new Image("photo.jpg"));
for (const auto& item : items) {
item->print();
}
// 清理
for (auto item : items) {
delete item;
}
return 0;
}多个接口
cpp
#include <iostream>
// 接口1:可绘制
class Drawable {
public:
virtual void draw() const = 0;
virtual ~Drawable() = default;
};
// 接口2:可缩放
class Scalable {
public:
virtual void scale(double factor) = 0;
virtual ~Scalable() = default;
};
// 同时实现多个接口
class Circle : public Drawable, public Scalable {
private:
double radius;
public:
Circle(double r) : radius(r) {}
void draw() const override {
std::cout << "Drawing circle with radius " << radius << std::endl;
}
void scale(double factor) override {
radius *= factor;
std::cout << "Scaled to radius " << radius << std::endl;
}
};
int main() {
Circle circle(5.0);
circle.draw();
circle.scale(2.0);
circle.draw();
return 0;
}接口设计原则
接口隔离原则(ISP)
cpp
// 糟糕的接口 - 太大
class WorkerInterface {
public:
virtual void work() = 0;
virtual void eat() = 0;
virtual void sleep() = 0;
};
// 好的接口 - 分离职责
class Workable {
public:
virtual void work() = 0;
virtual ~Workable() = default;
};
class Eatable {
public:
virtual void eat() = 0;
virtual ~Eatable() = default;
};
class Human : public Workable, public Eatable {
public:
void work() override {
std::cout << "Working..." << std::endl;
}
void eat() override {
std::cout << "Eating..." << std::endl;
}
};
class Robot : public Workable {
public:
void work() override {
std::cout << "Working..." << std::endl;
}
};依赖倒置原则(DIP)
cpp
// 高层模块不应依赖低层模块
class Switchable {
public:
virtual void turnOn() = 0;
virtual void turnOff() = 0;
virtual ~Switchable() = default;
};
class LightBulb : public Switchable {
public:
void turnOn() override {
std::cout << "Light is ON" << std::endl;
}
void turnOff() override {
std::cout << "Light is OFF" << std::endl;
}
};
class Fan : public Switchable {
public:
void turnOn() override {
std::cout << "Fan is ON" << std::endl;
}
void turnOff() override {
std::cout << "Fan is OFF" << std::endl;
}
};
// 高层模块
class Switch {
private:
Switchable& device;
bool on = false;
public:
Switch(Switchable& d) : device(d) {}
void toggle() {
if (on) {
device.turnOff();
} else {
device.turnOn();
}
on = !on;
}
};常见接口模式
迭代器接口
cpp
template<typename T>
class Iterator {
public:
virtual bool hasNext() const = 0;
virtual T next() = 0;
virtual ~Iterator() = default;
};
template<typename T>
class Container {
public:
virtual Iterator<T>* createIterator() const = 0;
virtual void add(const T& item) = 0;
virtual ~Container() = default;
};
// 具体实现
template<typename T>
class ListContainer : public Container<T> {
private:
std::vector<T> items;
public:
void add(const T& item) override {
items.push_back(item);
}
Iterator<T>* createIterator() const override {
return new ListIterator(items);
}
private:
class ListIterator : public Iterator<T> {
private:
const std::vector<T>& items;
size_t index = 0;
public:
ListIterator(const std::vector<T>& i) : items(i) {}
bool hasNext() const override {
return index < items.size();
}
T next() override {
return items[index++];
}
};
};观察者接口
cpp
#include <vector>
#include <string>
class Observer {
public:
virtual void update(const std::string& message) = 0;
virtual ~Observer() = default;
};
class Subject {
private:
std::vector<Observer*> observers;
protected:
void notify(const std::string& message) {
for (auto* observer : observers) {
observer->update(message);
}
}
public:
void addObserver(Observer* observer) {
observers.push_back(observer);
}
void removeObserver(Observer* observer) {
auto it = std::find(observers.begin(), observers.end(), observer);
if (it != observers.end()) {
observers.erase(it);
}
}
};
class NewsPublisher : public Subject {
public:
void publishNews(const std::string& news) {
std::cout << "Publishing: " << news << std::endl;
notify(news);
}
};
class EmailSubscriber : public Observer {
public:
void update(const std::string& message) override {
std::cout << "Email notification: " << message << std::endl;
}
};
class SMSSubscriber : public Observer {
public:
void update(const std::string& message) override {
std::cout << "SMS notification: " << message << std::endl;
}
};比较器接口
cpp
template<typename T>
class Comparator {
public:
virtual bool compare(const T& a, const T& b) const = 0;
virtual ~Comparator() = default;
};
class IntComparator : public Comparator<int> {
public:
bool compare(const int& a, const int& b) const override {
return a < b;
}
};
template<typename T>
void sortArray(std::vector<T>& arr, const Comparator<T>& comp) {
for (size_t i = 0; i < arr.size(); ++i) {
for (size_t j = i + 1; j < arr.size(); ++j) {
if (comp.compare(arr[j], arr[i])) {
std::swap(arr[i], arr[j]);
}
}
}
}接口与抽象类的区别
| 特性 | 接口 | 抽象类 |
|---|---|---|
| 方法实现 | 无 | 可以有 |
| 数据成员 | 无 | 可以有 |
| 构造函数 | 无 | 可以有 |
| 继承 | 多重 | 单一(C++) |
| 用途 | 定义行为契约 | 共享实现 |
cpp
// 纯接口
class IInterface {
public:
virtual void method() = 0;
virtual ~IInterface() = default;
};
// 抽象类
class AbstractClass {
protected:
int value;
public:
AbstractClass(int v) : value(v) {}
virtual void method() = 0;
void commonMethod() {
// 共享的实现
value += 1;
}
};C++11/14/17 中的接口
override 关键字
cpp
class Base {
public:
virtual void func() {}
};
class Derived : public Base {
public:
void func() override { // 明确表示覆盖
std::cout << "Derived::func()" << std::endl;
}
};final 关键字
cpp
class Base final { // 不能被继承
public:
virtual void func() {}
};
class Derived : public Base { // 编译错误
};cpp
class Base {
public:
virtual void func() final { // 不能被重写
}
};
class Derived : public Base {
public:
void func() override { // 编译错误
}
};默认实现
cpp
class Interface {
public:
virtual void method() = 0;
virtual ~Interface() = default; // 默认析构函数
};
class Implementation : public Interface {
public:
void method() override {
std::cout << "Method implementation" << std::endl;
}
};最佳实践
1. 使用虚析构函数
cpp
class Interface {
public:
virtual void method() = 0;
virtual ~Interface() { // 重要!
std::cout << "Interface destructor" << std::endl;
}
};2. 遵循命名约定
cpp
// 使用 I 前缀标识接口
class IShape {
public:
virtual double area() const = 0;
virtual ~IShape() = default;
};3. 保持接口简洁
cpp
// 好的接口 - 单一职责
class IWriter {
public:
virtual void write(const std::string& data) = 0;
virtual ~IWriter() = default;
};
// 糟糕的接口 - 职责过多
class IFileSystem {
public:
virtual void write(const std::string& data) = 0;
virtual void read(std::string& data) = 0;
virtual void compress() = 0;
virtual void encrypt() = 0;
// ... 太多功能
};4. 使用智能指针
cpp
#include <memory>
std::unique_ptr<Interface> createObject() {
return std::make_unique<Implementation>();
}
void useInterface(std::unique_ptr<Interface> obj) {
obj->method();
// 自动清理
}实际应用示例
数据库接口
cpp
class IDatabase {
public:
virtual void connect(const std::string& connectionString) = 0;
virtual void executeQuery(const std::string& query) = 0;
virtual void disconnect() = 0;
virtual ~IDatabase() = default;
};
class MySQLDatabase : public IDatabase {
public:
void connect(const std::string& conn) override {
std::cout << "Connecting to MySQL: " << conn << std::endl;
}
void executeQuery(const std::string& query) override {
std::cout << "Executing MySQL query: " << query << std::endl;
}
void disconnect() override {
std::cout << "Disconnecting from MySQL" << std::endl;
}
};
class PostgreSQLDatabase : public IDatabase {
public:
void connect(const std::string& conn) override {
std::cout << "Connecting to PostgreSQL: " << conn << std::endl;
}
void executeQuery(const std::string& query) override {
std::cout << "Executing PostgreSQL query: " << query << std::endl;
}
void disconnect() override {
std::cout << "Disconnecting from PostgreSQL" << std::endl;
}
};
void useDatabase(IDatabase& db) {
db.connect("localhost");
db.executeQuery("SELECT * FROM users");
db.disconnect();
}日志接口
cpp
enum class LogLevel { DEBUG, INFO, WARNING, ERROR };
class ILogger {
public:
virtual void log(LogLevel level, const std::string& message) = 0;
virtual ~ILogger() = default;
};
class ConsoleLogger : public ILogger {
public:
void log(LogLevel level, const std::string& message) override {
std::cout << "[" << static_cast<int>(level) << "] "
<< message << std::endl;
}
};
class FileLogger : public ILogger {
private:
std::ofstream logFile;
public:
FileLogger(const std::string& filename) {
logFile.open(filename, std::ios::app);
}
void log(LogLevel level, const std::string& message) override {
if (logFile.is_open()) {
logFile << "[" << static_cast<int>(level) << "] "
<< message << std::endl;
}
}
~FileLogger() {
if (logFile.is_open()) {
logFile.close();
}
}
};总结
- 接口:通过抽象类和纯虚函数实现
- 纯虚函数:以
= 0结尾,派生类必须实现 - 虚析构函数:确保正确清理资源
- 多重接口:类可以实现多个接口
- SOLID 原则:接口隔离、依赖倒置
- 智能指针:使用 unique_ptr/shared_ptr 管理接口对象