Skip to content

C++ 接口(抽象类)

接口是一种特殊的抽象类,它只包含纯虚函数,用于定义一组相关的操作。接口提供了对象之间的通信协议,而不关心具体的实现细节。

1. 接口的基本概念

接口是一种特殊的抽象类,它具有以下特点:

  1. 只包含纯虚函数
  2. 不包含数据成员
  3. 不包含构造函数和析构函数
  4. 所有成员函数都是public

1.1 示例

cpp
#include <iostream>

class Shape {
public:
    virtual double area() = 0;
    virtual double perimeter() = 0;
};

class Circle : public Shape {
private:
    double radius;

public:
    Circle(double radius) : radius(radius) {}
    
    double area() override {
        return 3.14159 * radius * radius;
    }
    
    double perimeter() override {
        return 2 * 3.14159 * radius;
    }
};

class Rectangle : public Shape {
private:
    double width;
    double height;

public:
    Rectangle(double width, double height) : width(width), height(height) {}
    
    double area() override {
        return width * height;
    }
    
    double perimeter() override {
        return 2 * (width + height);
    }
};

int main() {
    Shape* shape;
    
    Circle circle(5.0);
    Rectangle rectangle(4.0, 6.0);
    
    shape = &circle;
    std::cout << "圆的面积: " << shape->area() << std::endl;
    std::cout << "圆的周长: " << shape->perimeter() << std::endl;
    
    shape = &rectangle;
    std::cout << "矩形的面积: " << shape->area() << std::endl;
    std::cout << "矩形的周长: " << shape->perimeter() << std::endl;
    
    return 0;
}

2. 接口的定义

2.1 基本语法

cpp
class 接口名 {
public:
    virtual 返回类型 函数名(参数列表) = 0;
    virtual 返回类型 函数名(参数列表) = 0;
};

示例

cpp
#include <iostream>

class Printable {
public:
    virtual void print() = 0;
};

class Document : public Printable {
private:
    std::string content;

public:
    Document(std::string content) : content(content) {}
    
    void print() override {
        std::cout << "文档内容: " << content << std::endl;
    }
};

class Image : public Printable {
private:
    std::string filename;

public:
    Image(std::string filename) : filename(filename) {}
    
    void print() override {
        std::cout << "图片文件: " << filename << std::endl;
    }
};

int main() {
    Printable* printable;
    
    Document document("这是一份文档");
    Image image("image.jpg");
    
    printable = &document;
    printable->print();
    
    printable = &image;
    printable->print();
    
    return 0;
}

3. 接口的实现

3.1 实现单个接口

cpp
#include <iostream>

class Flyable {
public:
    virtual void fly() = 0;
};

class Bird : public Flyable {
public:
    void fly() override {
        std::cout << "鸟儿在飞翔" << std::endl;
    }
};

class Airplane : public Flyable {
public:
    void fly() override {
        std::cout << "飞机在飞行" << std::endl;
    }
};

int main() {
    Flyable* flyable;
    
    Bird bird;
    Airplane airplane;
    
    flyable = &bird;
    flyable->fly();
    
    flyable = &airplane;
    flyable->fly();
    
    return 0;
}

3.2 实现多个接口

cpp
#include <iostream>

class Flyable {
public:
    virtual void fly() = 0;
};

class Swimmable {
public:
    virtual void swim() = 0;
};

class Duck : public Flyable, public Swimmable {
public:
    void fly() override {
        std::cout << "鸭子在飞翔" << std::endl;
    }
    
    void swim() override {
        std::cout << "鸭子在游泳" << std::endl;
    }
};

class Fish : public Swimmable {
public:
    void swim() override {
        std::cout << "鱼在游泳" << std::endl;
    }
};

int main() {
    Duck duck;
    Fish fish;
    
    Flyable* flyable = &duck;
    flyable->fly();
    
    Swimmable* swimmable;
    
    swimmable = &duck;
    swimmable->swim();
    
    swimmable = &fish;
    swimmable->swim();
    
    return 0;
}

4. 接口和多态

接口是实现多态的重要方式。

cpp
#include <iostream>
#include <vector>

class Drawable {
public:
    virtual void draw() = 0;
};

class Circle : public Drawable {
private:
    double radius;

public:
    Circle(double radius) : radius(radius) {}
    
    void draw() override {
        std::cout << "绘制一个半径为 " << radius << " 的圆" << std::endl;
    }
};

class Rectangle : public Drawable {
private:
    double width;
    double height;

public:
    Rectangle(double width, double height) : width(width), height(height) {}
    
    void draw() override {
        std::cout << "绘制一个宽为 " << width << " 高为 " << height << " 的矩形" << std::endl;
    }
};

class Triangle : public Drawable {
private:
    double base;
    double height;

public:
    Triangle(double base, double height) : base(base), height(height) {}
    
    void draw() override {
        std::cout << "绘制一个底为 " << base << " 高为 " << height << " 的三角形" << std::endl;
    }
};

int main() {
    std::vector<Drawable*> shapes;
    
    shapes.push_back(new Circle(5.0));
    shapes.push_back(new Rectangle(4.0, 6.0));
    shapes.push_back(new Triangle(3.0, 4.0));
    
    for (Drawable* shape : shapes) {
        shape->draw();
    }
    
    for (Drawable* shape : shapes) {
        delete shape;
    }
    
    return 0;
}

5. 接口和抽象类的区别

特性接口抽象类
数据成员不包含可以包含
构造函数不包含可以包含
析构函数不包含可以包含
成员函数只包含纯虚函数可以包含纯虚函数和普通函数
访问修饰符所有成员都是public可以使用privateprotectedpublic

5.1 抽象类示例

cpp
#include <iostream>

class Animal {
protected:
    std::string name;

public:
    Animal(std::string name) : name(name) {}
    
    virtual void make_sound() = 0;
    
    void introduce() {
        std::cout << "我是 " << name << std::endl;
    }
};

class Dog : public Animal {
public:
    Dog(std::string name) : Animal(name) {}
    
    void make_sound() override {
        std::cout << "汪汪" << std::endl;
    }
};

class Cat : public Animal {
public:
    Cat(std::string name) : Animal(name) {}
    
    void make_sound() override {
        std::cout << "喵喵" << std::endl;
    }
};

int main() {
    Dog dog("旺财");
    Cat cat("咪咪");
    
    dog.introduce();
    dog.make_sound();
    
    cat.introduce();
    cat.make_sound();
    
    return 0;
}

6. 接口的应用

6.1 数据库接口

cpp
#include <iostream>
#include <string>

class Database {
public:
    virtual void connect() = 0;
    virtual void disconnect() = 0;
    virtual void query(std::string sql) = 0;
};

class MySQLDatabase : public Database {
public:
    void connect() override {
        std::cout << "连接到 MySQL 数据库" << std::endl;
    }
    
    void disconnect() override {
        std::cout << "断开 MySQL 数据库连接" << std::endl;
    }
    
    void query(std::string sql) override {
        std::cout << "执行 MySQL 查询: " << sql << std::endl;
    }
};

class PostgreSQLDatabase : public Database {
public:
    void connect() override {
        std::cout << "连接到 PostgreSQL 数据库" << std::endl;
    }
    
    void disconnect() override {
        std::cout << "断开 PostgreSQL 数据库连接" << std::endl;
    }
    
    void query(std::string sql) override {
        std::cout << "执行 PostgreSQL 查询: " << sql << std::endl;
    }
};

int main() {
    Database* database;
    
    MySQLDatabase mysql;
    PostgreSQLDatabase postgresql;
    
    database = &mysql;
    database->connect();
    database->query("SELECT * FROM users");
    database->disconnect();
    
    std::cout << std::endl;
    
    database = &postgresql;
    database->connect();
    database->query("SELECT * FROM products");
    database->disconnect();
    
    return 0;
}

6.2 支付接口

cpp
#include <iostream>
#include <string>

class Payment {
public:
    virtual void pay(double amount) = 0;
    virtual void refund(double amount) = 0;
};

class CreditCardPayment : public Payment {
public:
    void pay(double amount) override {
        std::cout << "使用信用卡支付: " << amount << " 元" << std::endl;
    }
    
    void refund(double amount) override {
        std::cout << "信用卡退款: " << amount << " 元" << std::endl;
    }
};

class WeChatPayment : public Payment {
public:
    void pay(double amount) override {
        std::cout << "使用微信支付: " << amount << " 元" << std::endl;
    }
    
    void refund(double amount) override {
        std::cout << "微信退款: " << amount << " 元" << std::endl;
    }
};

class AlipayPayment : public Payment {
public:
    void pay(double amount) override {
        std::cout << "使用支付宝支付: " << amount << " 元" << std::endl;
    }
    
    void refund(double amount) override {
        std::cout << "支付宝退款: " << amount << " 元" << std::endl;
    }
};

int main() {
    Payment* payment;
    
    CreditCardPayment credit_card;
    WeChatPayment wechat;
    AlipayPayment alipay;
    
    payment = &credit_card;
    payment->pay(100.0);
    payment->refund(50.0);
    
    std::cout << std::endl;
    
    payment = &wechat;
    payment->pay(200.0);
    payment->refund(100.0);
    
    std::cout << std::endl;
    
    payment = &alipay;
    payment->pay(300.0);
    payment->refund(150.0);
    
    return 0;
}

7. 示例:综合运用

现在,让我们看一个综合运用各种接口特性的例子:

cpp
#include <iostream>
#include <vector>

class Drawable {
public:
    virtual void draw() = 0;
};

class Resizable {
public:
    virtual void resize(double factor) = 0;
};

class Movable {
public:
    virtual void move(double x, double y) = 0;
};

class Shape : public Drawable, public Resizable, public Movable {
protected:
    double x;
    double y;

public:
    Shape(double x, double y) : x(x), y(y) {}
    
    void move(double x, double y) override {
        this->x = x;
        this->y = y;
        std::cout << "移动到 (" << x << ", " << y << ")" << std::endl;
    }
};

class Circle : public Shape {
private:
    double radius;

public:
    Circle(double x, double y, double radius) : Shape(x, y), radius(radius) {}
    
    void draw() override {
        std::cout << "绘制圆,圆心: (" << x << ", " << y << "),半径: " << radius << std::endl;
    }
    
    void resize(double factor) override {
        radius *= factor;
        std::cout << "调整圆的大小,新半径: " << radius << std::endl;
    }
};

class Rectangle : public Shape {
private:
    double width;
    double height;

public:
    Rectangle(double x, double y, double width, double height) : Shape(x, y), width(width), height(height) {}
    
    void draw() override {
        std::cout << "绘制矩形,位置: (" << x << ", " << y << "),宽: " << width << ",高: " << height << std::endl;
    }
    
    void resize(double factor) override {
        width *= factor;
        height *= factor;
        std::cout << "调整矩形的大小,新宽: " << width << ",新高: " << height << std::endl;
    }
};

int main() {
    std::vector<Shape*> shapes;
    
    shapes.push_back(new Circle(0, 0, 5.0));
    shapes.push_back(new Rectangle(10, 10, 4.0, 6.0));
    
    for (Shape* shape : shapes) {
        shape->draw();
        shape->resize(1.5);
        shape->move(20, 20);
        shape->draw();
        std::cout << std::endl;
    }
    
    for (Shape* shape : shapes) {
        delete shape;
    }
    
    return 0;
}

小结

C++ 接口(抽象类)包括:

  1. 接口的基本概念

    • 接口是一种特殊的抽象类
    • 只包含纯虚函数
    • 不包含数据成员
    • 不包含构造函数和析构函数
    • 所有成员函数都是public
  2. 接口的定义

    • 基本语法:class 接口名 { public: virtual 返回类型 函数名(参数列表) = 0; };
  3. 接口的实现

    • 实现单个接口
    • 实现多个接口
  4. 接口和多态

    • 接口是实现多态的重要方式
  5. 接口和抽象类的区别

    • 接口:只包含纯虚函数,不包含数据成员
    • 抽象类:可以包含纯虚函数和普通函数,可以包含数据成员
  6. 接口的应用

    • 数据库接口
    • 支付接口
    • 其他需要定义操作协议的场景

关键概念:

  • 接口:一种特殊的抽象类,只包含纯虚函数
  • 纯虚函数:在基类中声明但没有实现的虚函数
  • 抽象类:包含至少一个纯虚函数的类
  • 多态:同一个函数调用在不同对象上产生不同的行为

掌握接口是 C++ 面向对象编程的重要基础,在后续章节中,我们将学习 C++ 的高级教程。