C++虚函数与多态机制
C++虚函数与多态机制
虚函数是C++实现运行时多态的核心机制。通过虚函数表和虚函数指针,C++能够在运行时根据对象的实际类型调用相应的函数实现。
虚函数的基本语法使用virtual关键字声明,派生类可以重写基类的虚函数。
#include
#include
#include
class Animal {
public:
virtual ~Animal() = default;
virtual void make_sound() const {
std::cout << "Animal makes a sound\n";
}
virtual void move() const {
std::cout << "Animal moves\n";
}
void describe() const {
std::cout << "This is an animal\n";
}
};
class Dog : public Animal {
public:
void make_sound() const override {
std::cout << "Dog barks: Woof!\n";
}
void move() const override {
std::cout << "Dog runs on four legs\n";
}
};
class Cat : public Animal {
public:
void make_sound() const override {
std::cout << "Cat meows: Meow!\n";
}
void move() const override {
std::cout << "Cat walks gracefully\n";
}
};
void polymorphism_basic() {
std::vector> animals;
animals.push_back(std::make_unique());
animals.push_back(std::make_unique());
animals.push_back(std::make_unique());
for (const auto& animal : animals) {
animal->make_sound();
animal->move();
std::cout << "---\n";
}
}
纯虚函数使用=0语法声明,包含纯虚函数的类是抽象类,不能实例化。
class Shape {
public:
virtual ~Shape() = default;
virtual double area() const = 0;
virtual double perimeter() const = 0;
virtual void draw() const = 0;
};
class Circle : public Shape {
double radius_;
public:
explicit Circle(double r) : radius_(r) {}
double area() const override {
return 3.14159 * radius_ * radius_;
}
double perimeter() const override {
return 2 * 3.14159 * radius_;
}
void draw() const override {
std::cout << "Drawing circle with radius " << radius_ << "\n";
}
};
class Rectangle : public Shape {
double width_, height_;
public:
Rectangle(double w, double h) : width_(w), height_(h) {}
double area() const override {
return width_ * height_;
}
double perimeter() const override {
return 2 * (width_ + height_);
}
void draw() const override {
std::cout << "Drawing rectangle " << width_ << "x" << height_ << "\n";
}
};
void abstract_class_example() {
std::vector> shapes;
shapes.push_back(std::make_unique(5.0));
shapes.push_back(std::make_unique(4.0, 6.0));
double total_area = 0;
for (const auto& shape : shapes) {
shape->draw();
total_area += shape->area();
std::cout << "Area: " << shape->area() << ", Perimeter: " << shape->perimeter() << "\n";
}
std::cout << "Total area: " << total_area << "\n";
}
虚函数表是编译器实现虚函数的机制,每个包含虚函数的类都有一个虚函数表。
class Base {
public:
virtual void func1() { std::cout << "Base::func1\n"; }
virtual void func2() { std::cout << "Base::func2\n"; }
virtual ~Base() = default;
};
class Derived : public Base {
public:
void func1() override { std::cout << "Derived::func1\n"; }
void func3() { std::cout << "Derived::func3\n"; }
};
void vtable_demonstration() {
Base* ptr = new Derived();
ptr->func1();
ptr->func2();
delete ptr;
std::cout << "Size of Base: " << sizeof(Base) << "\n";
std::cout << "Size of Derived: " << sizeof(Derived) << "\n";
}
多重继承中的虚函数需要特别注意菱形继承问题。
class Device {
public:
virtual ~Device() = default;
virtual void power_on() = 0;
virtual void power_off() = 0;
};
class Printer : virtual public Device {
public:
void power_on() override {
std::cout << "Printer powered on\n";
}
void power_off() override {
std::cout << "Printer powered off\n";
}
virtual void print(const std::string& doc) {
std::cout << "Printing: " << doc << "\n";
}
};
class Scanner : virtual public Device {
public:
void power_on() override {
std::cout << "Scanner powered on\n";
}
void power_off() override {
std::cout << "Scanner powered off\n";
}
virtual void scan() {
std::cout << "Scanning document\n";
}
};
class MultiFunctionDevice : public Printer, public Scanner {
public:
void power_on() override {
std::cout << "Multi-function device powered on\n";
}
void power_off() override {
std::cout << "Multi-function device powered off\n";
}
};
void multiple_inheritance_example() {
MultiFunctionDevice mfd;
mfd.power_on();
mfd.print("document.pdf");
mfd.scan();
mfd.power_off();
}
final关键字可以防止类被继承或虚函数被重写。
class FinalClass final {
public:
virtual void func() {
std::cout << "FinalClass::func\n";
}
};
class BaseWithFinal {
public:
virtual void can_override() {
std::cout << "BaseWithFinal::can_override\n";
}
virtual void cannot_override() final {
std::cout << "BaseWithFinal::cannot_override\n";
}
};
class DerivedFromBase : public BaseWithFinal {
public:
void can_override() override {
std::cout << "DerivedFromBase::can_override\n";
}
};
协变返回类型允许派生类的虚函数返回更具体的类型。
class Product {
public:
virtual ~Product() = default;
virtual void use() const = 0;
};
class ConcreteProduct : public Product {
public:
void use() const override {
std::cout << "Using concrete product\n";
}
};
class Factory {
public:
virtual ~Factory() = default;
virtual Product* create() const {
return new Product();
}
};
class ConcreteFactory : public Factory {
public:
ConcreteProduct* create() const override {
return new ConcreteProduct();
}
};
虚析构函数确保通过基类指针删除派生类对象时能正确调用派生类的析构函数。
class ResourceBase {
public:
ResourceBase() {
std::cout << "ResourceBase constructor\n";
}
virtual ~ResourceBase() {
std::cout << "ResourceBase destructor\n";
}
};
class ResourceDerived : public ResourceBase {
int* data_;
public:
ResourceDerived() : data_(new int[100]) {
std::cout << "ResourceDerived constructor\n";
}
~ResourceDerived() override {
delete[] data_;
std::cout << "ResourceDerived destructor\n";
}
};
void virtual_destructor_example() {
ResourceBase* ptr = new ResourceDerived();
delete ptr;
}
动态类型识别使用dynamic_cast和typeid实现。
#include
class Component {
public:
virtual ~Component() = default;
virtual void update() = 0;
};
class GraphicsComponent : public Component {
public:
void update() override {
std::cout << "Updating graphics\n";
}
void render() {
std::cout << "Rendering graphics\n";
}
};
class PhysicsComponent : public Component {
public:
void update() override {
std::cout << "Updating physics\n";
}
void simulate() {
std::cout << "Simulating physics\n";
}
};
void rtti_example() {
std::vector> components;
components.push_back(std::make_unique());
components.push_back(std::make_unique());
for (auto& comp : components) {
comp->update();
if (auto* graphics = dynamic_cast(comp.get())) {
graphics->render();
} else if (auto* physics = dynamic_cast(comp.get())) {
physics->simulate();
}
std::cout << "Type: " << typeid(*comp).name() << "\n";
}
}
虚函数的性能开销主要来自间接调用和缓存未命中。
#include
class VirtualBase {
public:
virtual ~VirtualBase() = default;
virtual int compute(int x) const {
return x * x;
}
};
class VirtualDerived : public VirtualBase {
public:
int compute(int x) const override {
return x * x + x;
}
};
class NonVirtual {
public:
int compute(int x) const {
return x * x + x;
}
};
void performance_comparison() {
const int iterations = 10000000;
VirtualBase* vptr = new VirtualDerived();
auto start = std::chrono::high_resolution_clock::now();
volatile int result = 0;
for (int i = 0; i < iterations; ++i) {
result = vptr->compute(i);
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast(end - start);
std::cout << "Virtual call: " << duration.count() << " ms\n";
delete vptr;
NonVirtual nv;
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i) {
result = nv.compute(i);
}
end = std::chrono::high_resolution_clock::now();
duration = std::chrono::duration_cast(end - start);
std::cout << "Non-virtual call: " << duration.count() << " ms\n";
}
虚函数与模板结合可以实现静态多态和动态多态的混合使用。
template
class Processor {
public:
void process(const T& data) {
pre_process();
do_process(data);
post_process();
}
virtual ~Processor() = default;
protected:
virtual void pre_process() {
std::cout << "Default pre-processing\n";
}
virtual void do_process(const T& data) = 0;
virtual void post_process() {
std::cout << "Default post-processing\n";
}
};
class IntProcessor : public Processor {
protected:
void do_process(const int& data) override {
std::cout << "Processing int: " << data * 2 << "\n";
}
};
虚函数是C++面向对象编程的核心特性,理解其实现机制和使用场景对于设计灵活的系统至关重要。
