Skip to content

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 管理接口对象

相关教程

Content is for learning and research only.