目录C++虚函数1.虚函数基本感念1.1定义与声明1.2虚函数调用2.虚函数的工作原理2.1 虚函数表(vtable)2.2 内存结构示例3. 虚函数关键特性3.1 覆盖(override)3.2 纯虚函数4. 虚函数使用场景4.1 多态容器4.2 工厂模式5. 高级特性5.1 虚析构函数5.2 final关键字6. 性能考虑7. 最佳实践
C++虚函数
虚函数是C++实现运行时多态的核心机制,它允许通过基类指针或引用调用派生类的实现。下面我将全面介绍虚函数的概念、工作原理和使用方法。
纯虚函数(无实现体)类似与Java中的接口,虚函数(有实现体)类似与Java中的抽象方法。
1.虚函数基本感念
1.1定义与声明
使用virtual关键字来定义与声明成员函数
class Base {
public:
virtual void show() { // 虚函数声明
cout << "Base show()" << endl;
}
};
class Derived : public Base {
public:
void show() override { // 派生类重写
cout << "Derived show()" << endl;
}
};
1.2虚函数调用
通过基类指针或引用调用时,实际执行的是对象类型的版本:
Base* b = new Derived();
b->show(); // 输出"Derived show()"
2.虚函数的工作原理
2.1 虚函数表(vtable)
每个包含虚函数的类都有一个虚函数表
表中存放该类所有虚函数的地址
对象中包含指向vtable的指针(vptr)
2.2 内存结构示例
Derived 对象:
+----------------+
| vptr | --> Derived的vtable
| Base成员变量 | +----------------+
| Derived成员变量 | | &Derived::show |
+----------------+ +----------------+
3. 虚函数关键特性
3.1 覆盖(override)
派生类可以重写基类的虚函数:
class Animal {
public:
virtual void speak() {
cout << "Animal sound" << endl;
}
};
class Dog : public Animal {
public:
void speak() override { // 明确表示覆盖
cout << "Woof!" << endl;
}
};
3.2 纯虚函数
使类成为抽象基类:
class Shape {
public:
virtual void draw() = 0; // 纯虚函数
};
// 必须实现才能实例化
class Circle : public Shape {
public:
void draw() override {
cout << "Drawing circle" << endl;
}
};
4. 虚函数使用场景
4.1 多态容器
vector
zoo.push_back(new Dog());
zoo.push_back(new Cat());
for (auto animal : zoo) {
animal->speak(); // 调用各自实现
}
4.2 工厂模式
class Product {
public:
virtual void use() = 0;
};
class ConcreteProduct : public Product {
void use() override { /*...*/ }
};
Product* createProduct() {
return new ConcreteProduct();
}
5. 高级特性
5.1 虚析构函数
确保正确调用派生类析构函数:
class Base {
public:
virtual ~Base() {} // 虚析构函数
};
class Derived : public Base {
public:
~Derived() override { /* 清理资源 */ }
};
Base* b = new Derived();
delete b; // 正确调用Derived的析构函数
5.2 final关键字
禁止进一步覆盖:
class Base {
public:
virtual void foo() final {} // 禁止派生类覆盖
};
class Derived : public Base {
// void foo() override {} // 错误!不能覆盖final函数
};
6. 性能考虑
虚函数调用比普通函数多一次间接寻址
每个对象需要额外空间存储vptr
不适合在性能关键代码中过度使用
7. 最佳实践
多态基类的析构函数应该声明为虚函数
使用override明确表示覆盖意图
接口类使用纯虚函数
合理使用final优化设计
避免在构造函数/析构函数中调用虚函数
虚函数是C++面向对象编程的强大工具,正确使用可以实现灵活的多态设计,但也需要注意其开销和适用场景。