火柴人战争4无敌MOD
68.98MB · 2025-11-12
这是 C++ 面向对象编程中最核心的特性:虚函数(Virtual Function)和多态(Polymorphism)。让我详细解释:
// 接口类(抽象基类)
class ImageEditorProcessorListener {
public:
// 纯虚函数 (= 0 表示必须被子类实现)
virtual void onGetImageList(const std::string& id, std::string list, std::string host) = 0;
};
// 实现类1
class ImageEditorManager : public ImageEditorProcessorListener {
public:
// override 关键字表示重写父类虚函数
void onGetImageList(const std::string& id, std::string list, std::string host) override {
// 具体实现...
}
};
// 实现类2
class ImageListener : public IImageEditorListener {
public:
void onGetImageList(const std::string& id, std::string list, std::string host) override {
// 另一个实现...
}
};
// 在 ImageEditorProcessor.h 中
private:
std::shared_ptr<ImageEditorProcessorListener> mImageEditorProcessorListener;
// ↑ 声明类型是基类指针
// 在 ImageEditorManager.h 的 init() 方法中
void init() {
imageEditorProcessor = std::make_shared<ImageEditorProcessor>();
imageEditorProcessor->init();
// 关键代码:传入 ImageEditorManager 的 shared_ptr
imageEditorProcessor->setFileProcessorListener(shared_from_this());
// ↑ 实际类型是 ImageEditorManager
}
// setFileProcessorListener 的实现
void setFileProcessorListener(std::shared_ptr<ImageEditorProcessorListener> listener) {
mImageEditorProcessorListener = listener;
// 现在 mImageEditorProcessorListener 指向的是 ImageEditorManager 对象
}
关键点:
mImageEditorProcessorListener 的声明类型是 ImageEditorProcessorListener*(基类指针)ImageEditorManager 对象(派生类对象)当调用 mImageEditorProcessorListener->onGetImageList(...) 时:
编译器的处理流程:
1. 检查 mImageEditorProcessorListener 指向的对象的 vtable(虚函数表)
2. 在 vtable 中查找 onGetImageList 的实际实现地址
3. 发现实际对象是 ImageEditorManager
4. 跳转到 ImageEditorManager::onGetImageList()
虚函数表示意图:
ImageEditorProcessorListener 的 vtable:
├─ onGetImageList → [纯虚函数,无实现]
├─ onPreviewImage → [纯虚函数,无实现]
└─ ...
ImageEditorManager 的 vtable:
├─ onGetImageList → 指向 ImageEditorManager::onGetImageList 的地址
├─ onPreviewImage → 指向 ImageEditorManager::onPreviewImage 的地址
└─ ...
// ImageEditorManager.h
void onGetImageList(const std::string& id, std::string imageList, std::string host) override {
std::lock_guard<std::mutex> lock(fileListenerMutex);
// 遍历监听器列表
for (const auto& listener : imageEditorListenerList) {
// ↑ listener 的声明类型是 IImageEditorListener*
// 实际类型是 ImageListener*
listener->onGetImageList(id, imageList, host);
// 再次触发虚函数机制,跳转到 ImageListener::onGetImageList()
}
}
// 在某处注册监听器
private:
std::vector<std::shared_ptr<IImageEditorListener>> imageEditorListenerList;
// ↑ 基类指针容器
// 添加监听器时(实际是 ImageListener 对象)
imageEditorManager->addFileListener(std::make_shared<ImageListener>());
// ↑ 派生类对象,但存储为基类指针
class Base {
public:
virtual void func() { } // 虚函数
};
virtual 关键字声明class Interface {
public:
virtual void func() = 0; // 纯虚函数
};
= 0 语法class Derived : public Base {
public:
void func() override { } // 明确表示重写父类虚函数
};
必须满足:
Base* ptr = new Derived(); // 基类指针指向派生类对象
ptr->func(); // 调用的是 Derived::func(),而非 Base::func()
调用点:
mImageEditorProcessorListener->onGetImageList(deviceId, listStr, host)
↓
[运行时检查] mImageEditorProcessorListener 指向什么对象?
↓
指向 ImageEditorManager 对象
↓
通过 vtable 跳转到 ImageEditorManager::onGetImageList()
↓
for (listener : imageEditorListenerList) {
↓
[运行时检查] listener 指向什么对象?
↓
指向 ImageListener 对象
↓
通过 vtable 跳转到 ImageListener::onGetImageList()
↓
执行具体业务逻辑(下载图片、更新UI等)
}
ImageEditorProcessor 不需要知道具体的实现类就像打电话:
- 你拨的是"客服热线"(基类指针)
- 但接电话的是"小李"或"小王"(具体实现)
- 你不需要知道是谁接的,只需要知道能提供服务
#include <iostream>
#include <memory>
class Animal {
public:
virtual void speak() = 0; // 纯虚函数
};
class Dog : public Animal {
public:
void speak() override { std::cout << "汪汪!n"; }
};
class Cat : public Animal {
public:
void speak() override { std::cout << "喵喵!n"; }
};
int main() {
std::shared_ptr<Animal> animal1 = std::make_shared<Dog>();
std::shared_ptr<Animal> animal2 = std::make_shared<Cat>();
animal1->speak(); // 输出: 汪汪! (调用 Dog::speak)
animal2->speak(); // 输出: 喵喵! (调用 Cat::speak)
// 虽然都是 Animal 指针,但调用的是各自的实现
return 0;
}
这就是为什么 mImageEditorProcessorListener->onGetImageList() 能"自动"找到正确实现的原因!