C++虚函数与运行时多态
C++虚函数与运行时多态
虚函数通过虚函数表(vtable)和虚函数指针(vptr)实现运行时多态。当通过基类指针或引用调用虚函数时,程序根据对象的实际类型动态分派到正确的函数实现。
虚函数使用virtual关键字声明,派生类使用override关键字明确重写意图。
#include
#include
#include
#include
class Animal {
public:
virtual ~Animal() = default;
virtual void make_sound() const {
std::cout << "Animal makes a generic 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_demo() {
std::vector> animals;
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";
}
}
纯虚函数定义接口契约,包含纯虚函数的类是抽象类,不能实例化。
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.14159265358979 * radius_ * radius_;
}
double perimeter() const override {
return 2.0 * 3.14159265358979 * radius_;
}
void draw() const override {
std::cout << "Circle (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 << "Rectangle (" << width_ << "x" << height_ << ")\n";
}
};
void abstract_class_demo() {
std::vector> shapes;
shapes.push_back(std::make_unique(5.0));
shapes.push_back(std::make_unique(4.0, 6.0));
double total = 0;
for (const auto& s : shapes) {
s->draw();
total += s->area();
std::cout << "Area: " << s->area() << "\n";
}
std::cout << "Total area: " << total << "\n";
}
虚析构函数确保派生类正确析构。
class Base {
public:
Base() { std::cout << "Base constructed\n"; }
virtual ~Base() { std::cout << "Base destroyed\n"; }
};
class Derived : public Base {
int* data_;
public:
Derived() : data_(new int[100]) {
std::cout << "Derived constructed\n";
}
~Derived() override {
delete[] data_;
std::cout << "Derived destroyed\n";
}
};
void virtual_destructor_demo() {
Base* ptr = new Derived();
delete ptr;
}
dynamic_cast进行运行时类型转换。
void dynamic_cast_demo() {
std::vector> animals;
animals.push_back(std::make_unique());
animals.push_back(std::make_unique());
for (auto& animal : animals) {
if (Dog* dog = dynamic_cast(animal.get())) {
std::cout << "Found a dog\n";
} else if (Cat* cat = dynamic_cast(animal.get())) {
std::cout << "Found a cat\n";
}
}
}
typeid获取运行时类型信息。
void typeid_demo() {
std::unique_ptr animal = std::make_unique();
std::cout << "Type name: " << typeid(*animal).name() << "\n";
std::cout << "Is Dog: " << (typeid(*animal) == typeid(Dog)) << "\n";
std::cout << "Is Cat: " << (typeid(*animal) == typeid(Cat)) << "\n";
}
final关键字防止继承和重写。
class BaseFinal {
public:
virtual void func() final {
std::cout << "Cannot override\n";
}
};
多重接口继承。
class Printable {
public:
virtual ~Printable() = default;
virtual void print() const = 0;
};
class Serializable {
public:
virtual ~Serializable() = default;
virtual std::string serialize() const = 0;
};
class Document : public Printable, public Serializable {
std::string content_;
public:
explicit Document(const std::string& c) : content_(c) {}
void print() const override {
std::cout << content_ << "\n";
}
std::string serialize() const override {
return "DOC:" + content_;
}
};
void multiple_interface_demo() {
Document doc("Hello World");
doc.print();
std::cout << "Serialized: " << doc.serialize() << "\n";
}
协变返回类型。
class Cloneable {
public:
virtual Cloneable* clone() const { return new Cloneable(*this); }
};
class CloneableDerived : public Cloneable {
public:
CloneableDerived* clone() const override {
return new CloneableDerived(*this);
}
};
虚函数是实现运行时多态的基础,理解vtable机制有助于设计灵活的面向对象系统。