抽象类概念
在C++中,抽象类是一个无法实例化的类,通常用于定义接口或基类。抽象类的主要特征是至少包含一个纯虚函数(pure virtual function),这种函数在基类中没有实现,必须由派生类提供具体的实现。抽象类的主要作用是提供一个共享的接口,使得不同的派生类可以实现这些接口,从而实现多态性。
定义
抽象类通过在类中声明一个或多个纯虚函数来定义。纯虚函数的语法为:
cpp
virtual returnType functionName(parameters) = 0;
特点
- 不能实例化:抽象类本身不能创建对象。
- 可以包含其他函数:抽象类可以包含普通成员函数、静态成员函数和数据成员。
- 可以有构造函数:抽象类可以有构造函数,尽管不能直接实例化。
- 可以有实现的成员函数:不仅可以有纯虚函数,还可以有实现的普通成员函数。
使用抽象类的原因
- 接口设计:通过定义一个接口,强制派生类实现某些功能,以确保每个派生类都有统一的行为。
- 实现多态性:通过指向基类的指针或引用,可以调用派生类中实现的虚函数,实现运行时多态。
实例
cpp
#include <iostream>
using namespace std;
// 抽象类 Shape
class Shape {
public:
// 纯虚函数,表示没有实现
virtual void draw() = 0; // = 0 表示这是一个纯虚函数
virtual double area() = 0; // 计算面积的纯虚函数
};
// 派生类 Circle,继承自 Shape
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
void draw() override {
cout << "Drawing Circle with radius: " << radius << endl;
}
double area() override {
return 3.14159 * radius * radius; // 圆的面积计算
}
};
// 派生类 Rectangle,继承自 Shape
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
void draw() override {
cout << "Drawing Rectangle with width: " << width << ", height: " << height << endl;
}
double area() override {
return width * height; // 矩形的面积计算
}
};
int main() {
// Shape s; // 错误:无法实例化抽象类
Shape* shape1 = new Circle(5);
shape1->draw(); // 调用 Circle 的 draw
cout << "Area of Circle: " << shape1->area() << endl;
Shape* shape2 = new Rectangle(4, 6);
shape2->draw(); // 调用 Rectangle 的 draw
cout << "Area of Rectangle: " << shape2->area() << endl;
// 释放动态分配的内存
delete shape1;
delete shape2;
return 0;
}
- Shape 类:这是一个抽象类,其中定义了两个纯虚函数 draw() 和 area()。
- Circle 和 Rectangle 类:它们都是从 Shape 类派生的,必须实现 draw() 和 area() 这两个纯虚函数。
- 主函数:尝试实例化派生类 Circle 和 Rectangle,并通过基类指针 Shape* 调用它们的实现。通过虚函数机制保证了调用的是相应的实现。
纯虚函数
在C++中,纯虚函数(pure virtual function)是指在基类中声明但没有实现的虚函数。它用于定义接口并要求派生类实现这些函数。包含至少一个纯虚函数的类被称为抽象类(abstract class),这样的类不能被实例化。
定义
cpp
virtual returnType functionName(parameters) = 0;
其中,returnType是返回类型,functionName是函数名,而parameters是参数列表。= 0表明这个函数是纯虚函数。
特点
- 无实现:纯虚函数在基类中没有实现,派生类必须实现这个函数才能实例化对象。
- 实现多态性:通过基类的指针或引用来调用派生类中的实现。
- 抽象类:包含至少一个纯虚函数的类成为抽象类,无法直接创建其对象。
原因
- 设计接口:定义接口,确保所有派生类实现特定的功能。
- 实现多态:允许通过基类指针来调用派生类的实现,提供运行时多态性。
示例
cpp
#include <iostream>
using namespace std;
// 抽象类 Shape
class Shape {
public:
// 纯虚函数
virtual void draw() = 0; // = 0 声明这是一个纯虚函数
virtual double area() = 0; // 计算面积的纯虚函数
};
// 派生类 Circle,继承自 Shape
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
void draw() override {
cout << "Drawing Circle with radius: " << radius << endl;
}
double area() override {
return 3.14159 * radius * radius; // 圆的面积计算
}
};
// 派生类 Rectangle,继承自 Shape
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
void draw() override {
cout << "Drawing Rectangle with width: " << width << ", height: " << height << endl;
}
double area() override {
return width * height; // 矩形的面积计算
}
};
int main() {
// Shape s; // 错误:无法实例化抽象类
Shape* shape1 = new Circle(5);
shape1->draw(); // 调用 Circle 的 draw
cout << "Area of Circle: " << shape1->area() << endl;
Shape* shape2 = new Rectangle(4, 6);
shape2->draw(); // 调用 Rectangle 的 draw
cout << "Area of Rectangle: " << shape2->area() << endl;
// 释放动态分配的内存
delete shape1;
delete shape2;
return 0;
}
代码解析
-
抽象类 Shape:
- 定义了两个纯虚函数:draw()和area()。
- 这些函数没有函数体,意味着它们在 Shape 类中没有具体实现。
-
派生类 Circle 和 Rectangle:
- 这两个类实现了 Shape 接口,必须提供 draw() 和 area() 的具体实现。
- Circle 类提供了计算圆的面积和绘制圆的功能。
- Rectangle 类提供了计算矩形的面积和绘制矩形的功能。
-
主函数:
- 尝试创建 Circle 和 Rectangle 的对象,并使用基类指针 Shape* 调用它们的实现方法。
- 完成后,删除动态分配的对象以释放内存。