C&C++快速入门

21、多态

1、课程目标

  • 理解多态的概念
  • 掌握虚函数和纯虚函数
  • 理解虚函数表(vtable)
  • 掌握抽象类和接口

2、名词解释

术语 说明
多态 同一接口的不同实现
虚函数 virtual关键字修饰,可被重写
纯虚函数 = 0的虚函数,必须重写
抽象类 包含纯虚函数的类
vtable 虚函数表,存储虚函数地址
vptr 指向vtable的指针
重写 子类重新实现父类虚函数

3、代码实现

1. 虚函数基础

#include <iostream>
using namespace std;

class Shape {
public:
    virtual void Draw() {
        cout << "Drawing Shape" << endl;
    }
    
    virtual ~Shape() {
        cout << "~Shape" << endl;
    }
};

class Circle : public Shape {
public:
    void Draw() override {
        cout << "Drawing Circle" << endl;
    }
    
    ~Circle() {
        cout << "~Circle" << endl;
    }
};

class Rectangle : public Shape {
public:
    void Draw() override {
        cout << "Drawing Rectangle" << endl;
    }
};

int main() {
    cout << "=== 多态 ===" << endl << endl;
    
    Shape* shapes[] = {
        new Circle(),
        new Rectangle(),
        new Shape()
    };
    
    // 多态调用
    for (int i = 0; i < 3; i++) {
        shapes[i]->Draw();  // 根据实际类型调用
    }
    
    cout << "\n释放对象:" << endl;
    for (int i = 0; i < 3; i++) {
        delete shapes[i];
    }
    
    return 0;
}

2. 抽象类和接口

#include <iostream>
using namespace std;

// 抽象类(接口)
class IPlugin {
public:
    virtual void Initialize() = 0;  // 纯虚函数
    virtual void Execute() = 0;
    virtual void Cleanup() = 0;
    virtual ~IPlugin() {}
};

class LoggerPlugin : public IPlugin {
public:
    void Initialize() override {
        cout << "Logger: Initialize" << endl;
    }
    
    void Execute() override {
        cout << "Logger: Logging..." << endl;
    }
    
    void Cleanup() override {
        cout << "Logger: Cleanup" << endl;
    }
};

class NetworkPlugin : public IPlugin {
public:
    void Initialize() override {
        cout << "Network: Initialize" << endl;
    }
    
    void Execute() override {
        cout << "Network: Connecting..." << endl;
    }
    
    void Cleanup() override {
        cout << "Network: Cleanup" << endl;
    }
};

void RunPlugin(IPlugin* plugin) {
    plugin->Initialize();
    plugin->Execute();
    plugin->Cleanup();
}

int main() {
    cout << "=== 抽象类 ===" << endl << endl;
    
    LoggerPlugin logger;
    NetworkPlugin network;
    
    cout << "运行Logger:" << endl;
    RunPlugin(&logger);
    
    cout << "\n运行Network:" << endl;
    RunPlugin(&network);
    
    return 0;
}

3. 虚函数表查看

#include <iostream>
#include <windows.h>
using namespace std;

class Base {
public:
    virtual void Func1() { cout << "Base::Func1" << endl; }
    virtual void Func2() { cout << "Base::Func2" << endl; }
};

int main() {
    cout << "=== 虚函数表 ===" << endl << endl;
    
    Base obj;
    
    // 获取vptr (对象的第一个成员)
    void** vptr = *(void***)&obj;
    
    cout << "对象地址: " << &obj << endl;
    cout << "vtable地址: " << vptr << endl;
    cout << "Func1地址: " << vptr[0] << endl;
    cout << "Func2地址: " << vptr[1] << endl;
    
    // 通过vtable调用
    cout << "\n通过vtable调用:" << endl;
    typedef void (*VFunc)(Base*);
    ((VFunc)vptr[0])(&obj);
    ((VFunc)vptr[1])(&obj);
    
    return 0;
}

4、课后作业

4.1、作业1:实现动物类层次

实现Animal基类和Dog、Cat子类,使用多态。

4.2、作业2:解析vtable

手动解析一个类的虚函数表并调用其中的函数。