虚函数(Virtual Function)是C++中实现多态(Polymorphism)的关键机制。多态允许你通过基类指针或引用来调用派生类的成员函数,从而实现动态绑定(Dynamic Binding)。
虚函数在运行时决定调用哪一个函数,而不是在编译时决定。
1. 基本概念
- 虚函数:在基类中使用virtual关键字声明的成员函数。派生类可以重写(override)这个函数。
- 多态:通过基类指针或引用调用派生类的重写函数。
- 动态绑定:在运行时决定调用哪一个函数,而不是在编译时。
2. 基本语法
在基类中声明虚函数时使用virtual
关键字:
class Base {
public:
virtual void show() {
std::cout << "Base class" << std::endl;
}
};
class Derived : public Base {
public:
void show() override { // 重写基类的虚函数
std::cout << "Derived class" << std::endl;
}
};
示例代码
#include <iostream>
// 基类
class Base {
public:
virtual void show() {
std::cout << "Base class" << std::endl;
}
};
// 派生类
class Derived : public Base {
public:
void show() override {
std::cout << "Derived class" << std::endl;
}
};
void display(Base* obj) {
obj->show(); // 调用虚函数
}
int main() {
Base base;
Derived derived;
display(&base); // 输出 "Base class"
display(&derived); // 输出 "Derived class"
return 0;
}
输出:
Base class
Derived class
3. 纯虚函数和抽象类
纯虚函数是没有实现的虚函数,用于定义接口。包含纯虚函数的类称为抽象类,不能实例化。
class AbstractBase {
public:
virtual void show() = 0; // 纯虚函数
};
class ConcreteDerived : public AbstractBase {
public:
void show() override {
std::cout << "ConcreteDerived class" << std::endl;
}
};
int main() {
// AbstractBase obj; // 错误:不能实例化抽象类
ConcreteDerived derived;
derived.show(); // 输出 "ConcreteDerived class"
return 0;
}
输出:
ConcreteDerived class
4. 虚析构函数
在使用多态时,如果基类指针指向派生类对象,应该将基类的析构函数声明为虚函数(virtual),以确保正确调用派生类的析构函数。
#include <iostream>
class Base {
public:
virtual ~Base() {
std::cout << "Base destructor called" << std::endl;
}
};
class Derived : public Base {
public:
~Derived() {
std::cout << "Derived destructor called" << std::endl;
}
};
int main() {
Base* obj = new Derived();
delete obj; // 调用Derived的析构函数,然后调用Base的析构函数
return 0;
}
输出:
Derived destructor called
Base destructor called
5. 虚函数表(VTable)
虚函数的实现依赖于虚函数表(VTable)。每个包含虚函数的类都有一个虚函数表,表中存储了指向该类虚函数的指针。每个对象都有一个指向其类的虚函数表的指针(VPointer)。
示例:复杂继承结构中的虚函数
#include <iostream>
class Animal {
public:
virtual void sound() {
std::cout << "Some generic animal sound" << std::endl;
}
};
class Dog : public Animal {
public:
void sound() override {
std::cout << "Bark" << std::endl;
}
};
class Cat : public Animal {
public:
void sound() override {
std::cout << "Meow" << std::endl;
}
};
void makeSound(Animal* animal) {
animal->sound();
}
int main() {
Dog dog;
Cat cat;
makeSound(&dog); // 输出 "Bark"
makeSound(&cat); // 输出 "Meow"
return 0;
}
输出:
Bark
Meow
总结
- 虚函数:使用virtual关键字声明,在运行时决定调用哪个函数,实现多态。
- 纯虚函数和抽象类:纯虚函数用于定义接口,包含纯虚函数的类称为抽象类,不能实例化。
- 虚析构函数:在使用多态时,基类的析构函数应声明为虚函数,以确保正确调用派生类的析构函数。
- 虚函数表(VTable):虚函数的实现依赖于虚函数表,表中存储了指向虚函数的指针。
虚函数是C++中实现多态的重要机制,通过这些示例,可以了解虚函数的基本用法及其作用。合理使用虚函数可以使代码更加灵活和可扩展。