You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中为Spell添加可传自定义参数的函数指针并调用方案

问题描述

现有Spell类通过vector<function<void()>> _spell_effects存储技能效果,SpellManager在创建Spell时绑定固定参数的lambda作为效果。但调用InvokeEffect时无法传入自定义参数,所有效果只能用预设值。需要重构代码,实现调用技能效果时能传入自定义参数。

解决方案

1. 修改Spell类的效果存储与调用逻辑

把原有的无参function改成支持接收参数列表的类型,用function<void(vector<any>)>统一处理,这样调用时可以传入任意类型的参数。

修改Spell.h中的定义:

#include <any>
#include <vector>
#include <functional>

class Spell {
    // 原有属性(duration、cooldown等)保留
    std::vector<std::function<void(std::vector<std::any>)>> _spell_effects;
public:
    void SetSpellEffects(std::vector<std::function<void(std::vector<std::any>)>> spell_effects) {
        _spell_effects = spell_effects;
    }

    // 重构InvokeEffect,支持传入自定义参数
    void InvokeEffect(size_t index, std::vector<std::any> params = {}) {
        if (index < _spell_effects.size()) {
            _spell_effects[index](params);
        }
    }
};

2. 调整SpellManager中添加效果的方式

在AddSpellEffects里,把lambda改成接收vector<any>参数,内部解析参数后传递给实际的效果函数:

void SpellManager::AddSpellEffects(Spell* spell) {
    std::vector<std::function<void(std::vector<std::any>)>> effects;

    // 火球基础效果:解析玩家、敌人列表参数
    effects.push_back([this](std::vector<std::any> params) {
        if (params.size() < 2) return;
        PlayerCharacter* player = std::any_cast<PlayerCharacter*>(params[0]);
        std::vector<Character*>* enemies = std::any_cast<std::vector<Character*>*>(params[1]);
        this->Fireball_Default(player, *enemies);
    });

    // 火球2级效果:无参数直接调用
    effects.push_back([this](std::vector<std::any>) {
        this->Fireball_Level2();
    });

    // 火球3级效果:解析伤害参数,无参数时用默认值
    effects.push_back([this](std::vector<std::any> params) {
        int damage = 5;
        if (!params.empty()) {
            damage = std::any_cast<int>(params[0]);
        }
        this->Fireball_Level3(damage);
    });

    spell->SetSpellEffects(effects);
}

3. 调用时传入自定义参数

在业务代码里,根据不同效果的需求传入对应参数:

// 调用火球基础效果,传入玩家和敌人列表
std::vector<std::any> default_params;
default_params.push_back(player);
default_params.push_back(&_enemies);
player->GetActives()[0]->InvokeEffect(0, default_params);

// 调用火球3级效果,传入自定义伤害值10
std::vector<std::any> level3_params;
level3_params.push_back(10);
player->GetActives()[0]->InvokeEffect(2, level3_params);

// 调用火球2级效果,无需参数直接调用
player->GetActives()[0]->InvokeEffect(1);

可选优化:类型安全封装

如果担心any的类型不安全问题,可以为每个技能效果定义专属参数结构体:

// 定义火球基础效果的参数结构体
struct FireballDefaultParams {
    PlayerCharacter* caster;
    std::vector<Character*>* targets;
};

// 修改对应的lambda
effects.push_back([this](std::vector<std::any> params) {
    if (params.empty()) return;
    FireballDefaultParams* p = std::any_cast<FireballDefaultParams*>(params[0]);
    this->Fireball_Default(p->caster, *p->targets);
});

// 调用时传入结构体
FireballDefaultParams params{player, &_enemies};
player->GetActives()[0]->InvokeEffect(0, {&params});

内容的提问来源于stack exchange,提问作者crvenkapavica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:50:11