Appearance
C++ 接口(抽象类)
接口是一种特殊的抽象类,它只包含纯虚函数,用于定义一组相关的操作。接口提供了对象之间的通信协议,而不关心具体的实现细节。
1. 接口的基本概念
接口是一种特殊的抽象类,它具有以下特点:
- 只包含纯虚函数
- 不包含数据成员
- 不包含构造函数和析构函数
- 所有成员函数都是
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 = ℑ
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 | 可以使用private、protected、public |
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++ 接口(抽象类)包括:
接口的基本概念:
- 接口是一种特殊的抽象类
- 只包含纯虚函数
- 不包含数据成员
- 不包含构造函数和析构函数
- 所有成员函数都是
public的
接口的定义:
- 基本语法:
class 接口名 { public: virtual 返回类型 函数名(参数列表) = 0; };
- 基本语法:
接口的实现:
- 实现单个接口
- 实现多个接口
接口和多态:
- 接口是实现多态的重要方式
接口和抽象类的区别:
- 接口:只包含纯虚函数,不包含数据成员
- 抽象类:可以包含纯虚函数和普通函数,可以包含数据成员
接口的应用:
- 数据库接口
- 支付接口
- 其他需要定义操作协议的场景
关键概念:
- 接口:一种特殊的抽象类,只包含纯虚函数
- 纯虚函数:在基类中声明但没有实现的虚函数
- 抽象类:包含至少一个纯虚函数的类
- 多态:同一个函数调用在不同对象上产生不同的行为
掌握接口是 C++ 面向对象编程的重要基础,在后续章节中,我们将学习 C++ 的高级教程。