在C++中,虚函数和纯虚函数都与多态性和类的继承有关,但它们在功能和使用上存在一些区别。以下是它们之间的主要差异:
1. 定义:
- **虚函数 (Virtual Function)**: 虚函数在基类中声明,并可以在派生类中被重写(或称为覆盖)。虚函数在基类中具有默认的实现,但该实现可以在派生类中被覆盖。
- **纯虚函数 (Pure Virtual Function)**: 纯虚函数在基类中声明,但没有在基类中实现。它必须在派生类中被重写和实现。
2. 语法:
- **虚函数**: 在函数声明前加上关键字 `virtual`。
- **纯虚函数**: 在函数声明后面加上 `= 0`。例如:`virtual void functionName() = 0;`
3. 类的类型:
- 如果一个类包含至少一个纯虚函数,那么这个类就被称为抽象类。我们不能实例化一个抽象类,但可以使用指针或引用来指向这个类的对象。
- 含有虚函数的类可以被实例化,也可以被称为非抽象类。
4. 目的:
- **虚函数**: 允许基类为派生类提供一个默认的实现,但同时也提供了为这个函数提供不同实现的能力。
- **纯虚函数**: 强制派生类为这个函数提供一个实现,确保在派生类中有相应的方法实现。
5. 示例:
class Base {
public:
virtual void show() {
std::cout << "Base class's show";
}
virtual void display() = 0; // 纯虚函数
};
class Derived : public Base {
public:
void show() {
std::cout << "Derived class's show";
}
void display() {
std::cout << "Derived class's display"; // 必须实现纯虚函数
}
};
虚函数为派生类提供了重写基类函数的选择,而纯虚函数则强制派生类必须为其提供实现。
当一个类含有纯虚函数时,它就成为一个抽象类。抽象类无法被实例化,但可以通过指针或引用来引用派生类的对象。这种情况下,派生类必须实现抽象类中的纯虚函数。
以下是一个简单的例子来说明这一点:
#include <iostream>
class Shape {
public:
virtual void draw() = 0; // 纯虚函数
};
class Circle : public Shape {
public:
void draw() {
std::cout << "Drawing a circle." << std::endl;
}
};
class Square : public Shape {
public:
void draw() {
std::cout << "Drawing a square." << std::endl;
}
};
int main() {
// Shape shape; // 这会导致编译错误,因为Shape是抽象类,无法实例化
Circle circle;
Square square;
Shape* shapePtr1 = &circle; // 使用指针指向派生类对象
Shape* shapePtr2 = □
shapePtr1->draw(); // 调用派生类的实现
shapePtr2->draw();
return 0;
}
在上面的例子中,Shape
是一个抽象类,它含有纯虚函数 draw
。因此,无法创建 Shape
类的实例。但是,我们可以使用指针 shapePtr1
和 shapePtr2
来指向 Circle
和 Square
类的对象,并调用它们各自的 draw
函数,实现了多态性。