在 C++ 中,纯虚函数(pure virtual function)是一种特殊的虚函数,它在基类中没有实现,只定义了一个接口,要求派生类必须提供具体实现。纯虚函数的定义方式在接口设计和多态性中非常有用。
纯虚函数的定义和语法
在 C++ 中,纯虚函数的定义使用以下语法:
class Base {
public:
virtual void pureVirtualFunction() = 0; // 纯虚函数
};
- 这里
= 0
表示这是一个纯虚函数,它没有在Base
类中实现。 - 任何派生类都必须实现
pureVirtualFunction
,否则该派生类也会变成抽象类,不能被实例化。
抽象类
包含至少一个纯虚函数的类称为抽象类(abstract class)。抽象类不能直接创建对象(实例化)。它主要用于作为接口类或基类,要求派生类实现特定的行为。
例如:
class Shape {
public:
virtual void draw() = 0; // 纯虚函数
virtual double area() = 0; // 纯虚函数
};
class Circle : public Shape {
public:
void draw() override {
// Circle 的具体绘制实现
}
double area() override {
// 计算并返回 Circle 的面积
}
};
class Rectangle : public Shape {
public:
void draw() override {
// Rectangle 的具体绘制实现
}
double area() override {
// 计算并返回 Rectangle 的面积
}
};
在上面的例子中,Shape
是一个抽象类,定义了纯虚函数 draw
和 area
。任何继承自 Shape
的类(例如 Circle
和 Rectangle
)都必须实现这些函数。
纯虚函数的要求和特性
示例代码
下面是一个实际使用纯虚函数的示例:
-
纯虚函数不能在基类中实现: 纯虚函数在基类中没有实现,只有声明。这意味着它仅仅定义了一个接口或合同,具体实现由派生类提供。
-
派生类必须实现纯虚函数: 任何继承包含纯虚函数的类的非抽象派生类,必须实现这些纯虚函数,否则该派生类也会成为抽象类。
-
抽象类不能实例化: 包含纯虚函数的类不能直接创建对象(实例化)。它们通常用于定义接口和通用行为,强制派生类提供具体实现。
-
可以在派生类中覆盖实现: 派生类可以提供自己对纯虚函数的实现,这也是多态性的基础。例如,上面的
Circle
和Rectangle
都实现了Shape
的纯虚函数。 -
可以有实现的纯虚函数: 虽然纯虚函数本身在基类中没有实现,但在一些特殊情况下,可以为纯虚函数提供一个默认的实现,只是这种实现不会改变它作为纯虚函数的性质。例如:
class Base { public: virtual void pureVirtualFunction() = 0; // 纯虚函数 }; void Base::pureVirtualFunction() { // 纯虚函数的默认实现 }
-
这种情况下,派生类仍然需要实现
pureVirtualFunction
,否则它们将无法实例化。 -
使用纯虚函数的场景
-
定义接口: 纯虚函数常用于定义接口类,指定某些操作的合同,而不提供具体实现。例如,定义一个通信接口,要求所有的通信协议实现类都必须实现发送和接收方法。
-
强制派生类实现某些功能: 通过将函数声明为纯虚,基类可以强制派生类提供这些函数的具体实现,从而确保派生类具有一致的行为。
-
支持多态: 使用纯虚函数可以在运行时通过基类指针或引用调用派生类的实现,实现多态行为。
#include <iostream> class Animal { public: virtual void speak() = 0; // 纯虚函数 }; class Dog : public Animal { public: void speak() override { std::cout << "Woof!" << std::endl; } }; class Cat : public Animal { public: void speak() override { std::cout << "Meow!" << std::endl; } }; int main() { Animal* dog = new Dog(); Animal* cat = new Cat(); dog->speak(); // 输出: Woof! cat->speak(); // 输出: Meow! delete dog; delete cat; return 0; }
在这个例子中,
Animal
类定义了一个纯虚函数speak
。Dog
和Cat
类必须实现speak
函数。在main
函数中,通过基类指针调用派生类的speak
实现,实现了多态行为。