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

如何建自己的网站嵌入式培训班一般多少钱

如何建自己的网站,嵌入式培训班一般多少钱,大庆黄页查询电话,购物网站难做More Effective C 条款31:让函数根据多个对象来决定怎么虚拟核心思想:通过多重分发(Double Dispatch)和Visitor模式,实现基于多个对象类型的动态行为分发,解决单一虚拟函数机制无法处理的多态选择问题。 &a…

More Effective C++ 条款31:让函数根据多个对象来决定怎么虚拟


核心思想通过多重分发(Double Dispatch)和Visitor模式,实现基于多个对象类型的动态行为分发,解决单一虚拟函数机制无法处理的多态选择问题。

🚀 1. 问题本质分析

1.1 单一虚拟函数的局限性

  • 只能基于单个对象类型:虚函数根据this对象的动态类型进行分发
  • 无法处理多对象交互:当行为取决于两个或多个对象的类型时,虚函数机制不足
  • 组合爆炸问题:使用if-else或switch-case会导致代码冗余和难以维护
  • 类型耦合度高:添加新类型需要修改所有相关函数

1.2 多重分发的核心需求

  • 动态双分发:根据两个对象的动态类型选择行为
  • 扩展性:容易添加新类型和新操作
  • 类型安全:编译时类型检查
  • 解耦合:减少类型之间的相互依赖
// 基础示例:游戏对象碰撞检测问题
class GameObject;
class SpaceShip;
class SpaceStation;
class Asteroid;// 基础游戏对象类
class GameObject {
public:virtual ~GameObject() = default;virtual void collide(GameObject& other) = 0;// 需要为每个可能碰撞的类型提供接口virtual void collideWith(SpaceShip& ship) = 0;virtual void collideWith(SpaceStation& station) = 0;virtual void collideWith(Asteroid& asteroid) = 0;
};// 派生类需要实现所有碰撞组合
class SpaceShip : public GameObject {
public:void collide(GameObject& other) override {// 双重分发:让另一个对象处理碰撞other.collideWith(*this);}void collideWith(SpaceShip& ship) override {std::cout << "SpaceShip-SpaceShip collision\n";}void collideWith(SpaceStation& station) override {std::cout << "SpaceShip-SpaceStation collision\n";}void collideWith(Asteroid& asteroid) override {std::cout << "SpaceShip-Asteroid collision\n";}
};// 使用示例
void basicDoubleDispatch() {SpaceShip ship1, ship2;SpaceStation station;Asteroid asteroid;ship1.collide(ship2);     // SpaceShip-SpaceShip collisionship1.collide(station);   // SpaceShip-SpaceStation collisionship1.collide(asteroid);  // SpaceShip-Asteroid collision
}

📦 2. 问题深度解析

2.1 手动实现双重分发

// 更完善的双重分发实现
class SpaceShip;
class SpaceStation;
class Asteroid;
class Satellite; // 新类型class GameObject {
public:virtual ~GameObject() = default;// 主要碰撞接口virtual void collide(GameObject& other) = 0;// 具体的碰撞处理函数virtual void processCollision(SpaceShip& ship) = 0;virtual void processCollision(SpaceStation& station) = 0;virtual void processCollision(Asteroid& asteroid) = 0;virtual void processCollision(Satellite& satellite) = 0;
};// 实现基类提供默认碰撞处理
class DefaultCollisionHandler {
public:static void handleUnknownCollision(GameObject& obj1, GameObject& obj2) {std::cout << "Unknown collision between " << typeid(obj1).name() << " and " << typeid(obj2).name() << std::endl;}
};class SpaceShip : public GameObject {
public:void collide(GameObject& other) override {other.processCollision(*this);}void processCollision(SpaceShip& ship) override {std::cout << "Two spaceships collide\n";// 具体的碰撞处理逻辑}void processCollision(SpaceStation& station) override {std::cout << "Spaceship docks with station\n";}void processCollision(Asteroid& asteroid) override {std::cout << "Spaceship hit by asteroid!\n";}void processCollision(Satellite& satellite) override {std::cout << "Spaceship collides with satellite\n";}
};// 新类型需要实现所有碰撞处理
class Satellite : public GameObject {
public:void collide(GameObject& other) override {other.processCollision(*this);}void processCollision(SpaceShip& ship) override {std::cout << "Satellite hit by spaceship\n";}void processCollision(SpaceStation& station) override {std::cout << "Satellite docks with station\n";}void processCollision(Asteroid& asteroid) override {std::cout << "Satellite destroyed by asteroid\n";}void processCollision(Satellite& satellite) override {std::cout << "Two satellites collide\n";}
};// 使用示例
void advancedDoubleDispatch() {SpaceShip ship;SpaceStation station;Asteroid asteroid;Satellite satellite;// 自动选择正确的碰撞处理ship.collide(station);    // Spaceship docks with stationstation.collide(asteroid); // 需要SpaceStation实现相应方法satellite.collide(ship);  // Satellite hit by spaceship
}

2.2 使用函数指针表实现分发

// 基于映射表的多重分发
class GameObject;// 碰撞处理函数类型
using CollisionHandler = void(*)(GameObject&, GameObject&);// 全局碰撞处理映射表
class CollisionMap {
public:using Key = std::pair<std::type_index, std::type_index>;using Map = std::map<Key, CollisionHandler>;static void addHandler(const std::type_info& type1, const std::type_info& type2,CollisionHandler handler) {map_[Key(type1, type2)] = handler;// 添加对称处理map_[Key(type2, type1)] = handler;}static CollisionHandler getHandler(const std::type_info& type1,const std::type_info& type2) {auto it = map_.find(Key(type1, type2));if (it != map_.end()) {return it->second;}return nullptr;}private:static Map map_;
};// 初始化静态成员
CollisionMap::Map CollisionMap::map_;// 简化版游戏对象
class GameObject {
public:virtual ~GameObject() = default;virtual std::type_index type() const = 0;void collide(GameObject& other) {auto handler = CollisionMap::getHandler(type(), other.type());if (handler) {handler(*this, other);} else {std::cout << "No handler for collision between "<< type().name() << " and " << other.type().name() << std::endl;}}
};// 具体的碰撞处理函数
void handleShipAsteroid(GameObject& go1, GameObject& go2) {std::cout << "Handling spaceship-asteroid collision\n";// 可以安全转换,因为我们知道类型// SpaceShip& ship = static_cast<SpaceShip&>(go1);// Asteroid& asteroid = static_cast<Asteroid&>(go2);
}void handleShipStation(GameObject& go1, GameObject& go2) {std::cout << "Handling spaceship-station docking\n";
}// 注册碰撞处理
class CollisionRegistrar {
public:CollisionRegistrar() {CollisionMap::addHandler(typeid(SpaceShip), typeid(Asteroid), handleShipAsteroid);CollisionMap::addHandler(typeid(SpaceShip), typeid(SpaceStation), handleShipStation);}
};// 静态注册器
static CollisionRegistrar registrar;// 使用示例
void mapBasedDispatch() {SpaceShip ship;Asteroid asteroid;SpaceStation station;ship.collide(asteroid);  // Handling spaceship-asteroid collisionship.collide(station);   // Handling spaceship-station dockingGameObject* unknown = new SpaceShip;asteroid.collide(*unknown);  // 同样有效delete unknown;
}

⚖️ 3. 解决方案与最佳实践

3.1 Visitor模式实现多重分发

// 使用Visitor模式实现优雅的多重分发
class SpaceShip;
class SpaceStation;
class Asteroid;
class Satellite;// 前向声明
class GameObjectVisitor;// 可接受访问者的游戏对象
class GameObject {
public:virtual ~GameObject() = default;virtual void accept(GameObjectVisitor& visitor) = 0;virtual void collide(GameObject& other) = 0;
};// 访问者接口
class GameObjectVisitor {
public:virtual ~GameObjectVisitor() = default;virtual void visit(SpaceShip& ship) = 0;virtual void visit(SpaceStation& station) = 0;virtual void visit(Asteroid& asteroid) = 0;virtual void visit(Satellite& satellite) = 0;
};// 碰撞访问者
class CollisionVisitor : public GameObjectVisitor {
public:CollisionVisitor(GameObject& collider) : collider_(collider) {}void visit(SpaceShip& ship) override {handleCollision(ship, collider_);}void visit(SpaceStation& station) override {handleCollision(station, collider_);}void visit(Asteroid& asteroid) override {handleCollision(asteroid, collider_);}void visit(Satellite& satellite) override {handleCollision(satellite, collider_);}private:template<typename T1, typename T2>void handleCollision(T1& obj1, T2& obj2) {std::cout << "Collision between " << typeid(T1).name()<< " and " << typeid(T2).name() << std::endl;}GameObject& collider_;
};// 具体游戏对象实现
class SpaceShip : public GameObject {
public:void accept(GameObjectVisitor& visitor) override {visitor.visit(*this);}void collide(GameObject& other) override {CollisionVisitor visitor(*this);other.accept(visitor);}
};class SpaceStation : public GameObject {
public:void accept(GameObjectVisitor& visitor) override {visitor.visit(*this);}void collide(GameObject& other) override {CollisionVisitor visitor(*this);other.accept(visitor);}
};// 使用示例
void visitorPatternExample() {SpaceShip ship;SpaceStation station;Asteroid asteroid;ship.collide(station);   // 通过Visitor处理碰撞station.collide(asteroid);
}

3.2 使用std::variant和std::visit(C++17)

// 现代C++17实现多重分发
#include <variant>
#include <vector>// 游戏对象类型
class SpaceShip { 
public:void collideWith(SpaceShip&) { std::cout << "Ship-Ship\n"; }void collideWith(class SpaceStation&) { std::cout << "Ship-Station\n"; }void collideWith(class Asteroid&) { std::cout << "Ship-Asteroid\n"; }
};class SpaceStation {
public:void collideWith(SpaceShip&) { std::cout << "Station-Ship\n"; }void collideWith(SpaceStation&) { std::cout << "Station-Station\n"; }void collideWith(class Asteroid&) { std::cout << "Station-Asteroid\n"; }
};class Asteroid {
public:void collideWith(SpaceShip&) { std::cout << "Asteroid-Ship\n"; }void collideWith(SpaceStation&) { std::cout << "Asteroid-Station\n"; }void collideWith(Asteroid&) { std::cout << "Asteroid-Asteroid\n"; }
};// 使用variant包装所有类型
using GameObject = std::variant<SpaceShip, SpaceStation, Asteroid>;// 碰撞访问器
struct CollisionHandler {template<typename T1, typename T2>void operator()(T1& obj1, T2& obj2) {obj1.collideWith(obj2);}
};// 碰撞函数
void processCollision(GameObject& obj1, GameObject& obj2) {std::visit(CollisionHandler{}, obj1, obj2);
}// 使用示例
void variantBasedDispatch() {GameObject ship = SpaceShip();GameObject station = SpaceStation();GameObject asteroid = Asteroid();processCollision(ship, station);     // Ship-StationprocessCollision(ship, asteroid);    // Ship-AsteroidprocessCollision(station, asteroid); // Station-Asteroid// 可以存储在容器中std::vector<GameObject> objects{ship, station, asteroid};processCollision(objects[0], objects[1]);
}

3.3 类型安全的动态分发框架

// 类型安全的双重分发框架
template<typename Base, typename... Deriveds>
class DoubleDispatcher {
public:using Handler = std::function<void(Base&, Base&)>;template<typename T1, typename T2>void registerHandler(Handler handler) {auto key = std::make_pair(typeid(T1), typeid(T2));handlers_[key] = handler;// 注册对称处理auto symmetricKey = std::make_pair(typeid(T2), typeid(T1));handlers_[symmetricKey] = [handler](Base& a, Base& b) {handler(b, a); // 交换参数};}bool dispatch(Base& obj1, Base& obj2) {auto key = std::make_pair(typeid(obj1), typeid(obj2));auto it = handlers_.find(key);if (it != handlers_.end()) {it->second(obj1, obj2);return true;}return false;}private:std::map<std::pair<std::type_index, std::type_index>, Handler> handlers_;
};// 使用框架
class GameEntity {
public:virtual ~GameEntity() = default;
};class Player : public GameEntity {};
class Enemy : public GameEntity {};
class Projectile : public GameEntity {};void setupDispatcher(DoubleDispatcher<GameEntity>& dispatcher) {dispatcher.registerHandler<Player, Enemy>([](GameEntity& p, GameEntity& e) {std::cout << "Player hits Enemy\n";});dispatcher.registerHandler<Projectile, Enemy>([](GameEntity& proj, GameEntity& e) {std::cout << "Projectile hits Enemy\n";});dispatcher.registerHandler<Player, Projectile>([](GameEntity& p, GameEntity& proj) {std::cout << "Player hits Projectile\n";});
}// 使用示例
void frameworkExample() {DoubleDispatcher<GameEntity> dispatcher;setupDispatcher(dispatcher);Player player;Enemy enemy;Projectile projectile;dispatcher.dispatch(player, enemy);       // Player hits Enemydispatcher.dispatch(projectile, enemy);   // Projectile hits Enemydispatcher.dispatch(player, projectile);  // Player hits Projectile
}

💡 关键实践原则

  1. 选择适当的分发机制
    • 简单情况:手动双重分发
    • 中等复杂度:Visitor模式
    • 现代C++:std::variant + std::visit
    • 大型系统:自定义分发框架
  2. 考虑扩展性
    • 添加新类型时的影响范围
    • 新操作的添加难易程度
  3. 性能考量
    • 虚函数调用 vs 函数指针查找 vs 编译时分发
    • 缓存友好性
  4. 类型安全
    • 避免运行时类型错误
    • 提供合理的默认行为
  5. 代码组织
    • 集中管理分发逻辑
    • 良好的错误处理和日志记录

应用场景总结

// 1. 游戏开发:碰撞检测、技能效果
// 2. GUI系统:事件处理、控件交互
// 3. 编译器:AST节点处理
// 4. 数学库:表达式求值
// 5. 业务逻辑:多类型实体交互

C++中的多重分发技术演进

// 传统方法:虚函数 + RTTI
// 设计模式:Visitor模式
// 现代方法:std::variant + std::visit
// 高级技术:模板元编程 + 概念约束void evolutionExample() {// 传统方法(容易产生组合爆炸)// 现代方法(类型安全,易于扩展)// 未来方向(编译时多分发)
}

总结
多重分发是解决基于多个对象类型进行行为选择的强大技术,突破了C++单分发的限制。

从传统的手动双重分发到现代的std::visit方案,C++提供了多种实现方式。选择合适的方法需要考虑系统的复杂度、性能要求、扩展性需求和团队的技术水平。

良好的多重分发设计可以显著提高代码的可维护性和扩展性,特别是在处理复杂对象交互的场景中。现代C++特性如variant和visit为这个问题提供了更优雅、类型安全的解决方案。

http://www.dtcms.com/a/451917.html

相关文章:

  • 沈阳电力建设总公司网站自行创建网站的平台
  • 怎样为网站做外链知乎关键词搜索
  • 无锡好的网站建设公司厨师培训
  • 莆田网站建站建设中国科技成就的例子
  • dw如何建立网站建筑人才网招聘官网
  • 什么叫做响应式网站北京公司网站制作公司
  • 做水果代理去哪个网站做一个聊天软件多少钱
  • 农博园网站建设投标书济南网站制作厂家
  • 家装网站做深圳app制作公司
  • 网站运营的内容百度网站与推广
  • 珠海好的网站制作平台怎样做收费网站
  • 网站怎么添加域名昆山网站建设义搏
  • 空间购买后打不开网站西双版纳傣族自治州医院
  • 用阿里云服务器做自己购物网站医院网站 行风建设
  • 商城网站建设付款怎么实现泰安网站制作哪里有
  • 网站无域名注册人id房地产设计部岗位职责
  • aspcms网站模板服饰网站模板
  • 注册网站域名平台福州公司网站设计
  • 网站建设制作设计开发福建微网站怎么注册
  • golang 网站开发 开源中国纪检监察报邮箱
  • 关于网站建设的文章天津网络网站制作公司
  • 建电子商务网站注意事项无网站做百度推广
  • 软件 开发公司长沙seo行者seo09
  • 怎么做微课网站国外ip代理app
  • 聊城做网站的公司平台怎样做百度网站推广
  • 网站开发费的税率是多少广州白云手机网站建设
  • 网站开发检测用户微信号wordpress首页幻灯片设置
  • 合肥php网站开发钦州网站建设
  • 企业网站设计推广方案广告公司简介模板200字
  • 网站集约化建设进度汇报哪些网站做任务可以赚钱的