当前位置: 首页 > news >正文

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++面向对象编程的核心特性,理解其实现机制和使用场景对于设计灵活的系统至关重要。

http://www.jsqmd.com/news/873865/

相关文章:

  • 原来训大模型,就像开一家小餐馆!
  • 缅怀不朽功勋,汲取奋进力量——纪念张柏荣院士
  • 面向心理咨询 Agent 的 Harness 危机关键词拦截
  • FlexNet Publisher许可证文件合并实战指南
  • Docker 入门笔记(后端开发必学)
  • 事件驱动仿真技术在航天系统中的应用与优化
  • 电脑里的“大脑”和“画家”:CPU和GPU到底谁在偷偷帮你干活?
  • 观察Taotoken按Token计费模式如何帮助项目控制预算
  • 腾讯混元全新翻译模型Hy-MT2开源,小程序「腾讯Hy翻译」开放体验
  • Java并发编程:ReentrantLock与AQS原理剖析
  • 2026亲测10款降AIGC网站红黑榜!优缺点无死角剖析,达标率对标顶级水准
  • µVision调试器与SEGGER J-Link兼容性解析
  • 【咨询业AI Agent应用成熟度评估模型】:基于217家机构实测数据的4级能力图谱与升级路线图
  • Docker 日常操作笔记(开发最常用命令)
  • 为什么iPhone微信聊天记录搜不到“?“,而安卓可以。
  • 混合精度优化在LLM推理加速中的实践与调优
  • Keil MDK中System Viewer空白问题的解决方案
  • 社交AI Agent不是Chatbot!5个被99%团队忽略的协议层设计陷阱(附LinkedIn/小红书级SDK接口规范)
  • 通过curl命令直接测试Taotoken聊天补全接口的配置与调用方法
  • AI赋能 绿色未来 —— 华硕重磅亮相第二十八届海峡两岸经贸交易会
  • 3个实用方法彻底解决阅读APP书源失效问题
  • Docker 里面的镜像(Image)和容器(Container)到底是什么
  • Python爬虫实战:爬取论文期刊 文献整理+管理表生成
  • Claude不是在模仿人,是在重构认知:3个被忽略的递归反思协议(附企业级调优checklist)
  • 5个技巧让你用Python零成本获取A股专业数据
  • Python、BMA-Stacking融合LightGBM、GBDT、KNN多模型电商交易欺诈风险预警研究|附代码数据
  • Apple ID身份协商协议全解析:rO/scnt/m动态参数生成原理
  • 三亚夜市哪家最有特色 - 资讯纵览
  • pycryptodome导入失败的四大底层原因与诊断方案
  • 非球面高精加高精密恒温恒湿空调机组选哪家 - 资讯纵览