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

如何将成员函数指针传递给模板函数以消除C++代码冗余

代码冗余消除与成员函数指针使用修正

问题核心原因

原代码无法编译的关键错误有两个:

  • 成员函数指针传递错误:调用getNumbersSet时,误传了Base/Derived类的成员函数指针(如&Base::getNumbersSet1),但模板函数实际需要的是T(即SBase/SDerived)类型的成员函数指针。
  • std::bind用法错误:代码中&T::getNumberFunc是错误写法,getNumberFunc本身已经是T的成员函数指针,无需再取地址。

修正后的实现

1. 修正Base类的模板函数

直接通过成员函数指针调用,代码更简洁高效:

class Base {
public:
    virtual std::vector<int32_t> getNumbersSet1();
    virtual std::vector<int32_t> getNumbersSet2();
protected:
    std::vector<SBase> sVec;

private:
    template<class T>
    static std::vector<int32_t> getNumbersSet(const std::vector<T>& svec, std::vector<int32_t>(T::* getNumberFunc)() const) {
        std::vector<int32_t> retval;
        for (const T& a : svec) {
            // 直接通过成员函数指针调用目标方法
            std::vector<int32_t> tmp = (a.*getNumberFunc)();
            retval.insert(retval.end(), tmp.cbegin(), tmp.cend());
        }
        return retval; // 原代码遗漏return语句
    }
};

若坚持使用std::bind,正确写法如下:

template<class T>
static std::vector<int32_t> getNumbersSet(const std::vector<T>& svec, std::vector<int32_t>(T::* getNumberFunc)() const) {
    std::vector<int32_t> retval;
    for (const T& a : svec) {
        auto getNumbersOfT = std::bind(getNumberFunc, std::cref(a));
        std::vector<int32_t> tmp = getNumbersOfT();
        retval.insert(retval.end(), tmp.cbegin(), tmp.cend());
    }
    return retval;
}

2. 修正模板函数的调用代码

传递SBase/SDerived对应的成员函数指针,而非Base/Derived的:

// Base类成员函数实现
std::vector<int32_t> Base::getNumbersSet1() {
    return getNumbersSet<SBase>(sVec, &SBase::getNumbersSet1);
}

std::vector<int32_t> Base::getNumbersSet2() {
    return getNumbersSet<SBase>(sVec, &SBase::getNumbersSet2);
}

// Derived类成员函数实现
std::vector<int32_t> Derived::getNumbersSet1() {
    return Base::getNumbersSet<SDerived>(sVec, &SDerived::getNumbersSet1);
}

std::vector<int32_t> Derived::getNumbersSet2() {
    return Base::getNumbersSet<SDerived>(sVec, &SDerived::getNumbersSet2);
}

额外优化:消除Base与Derived的冗余

Derived类重新定义sVec会隐藏Base的同名成员,可将Base改为模板类进一步简化:

template<typename SType>
class BaseTemplate {
public:
    virtual std::vector<int32_t> getNumbersSet1() {
        return getNumbersSet(sVec, &SType::getNumbersSet1);
    }
    virtual std::vector<int32_t> getNumbersSet2() {
        return getNumbersSet(sVec, &SType::getNumbersSet2);
    }
protected:
    std::vector<SType> sVec;

private:
    template<class T>
    static std::vector<int32_t> getNumbersSet(const std::vector<T>& svec, std::vector<int32_t>(T::* getNumberFunc)() const) {
        std::vector<int32_t> retval;
        for (const T& a : svec) {
            std::vector<int32_t> tmp = (a.*getNumberFunc)();
            retval.insert(retval.end(), tmp.cbegin(), tmp.cend());
        }
        return retval;
    }
};

// 使用方式
class Base : public BaseTemplate<SBase> {};
class Derived : public BaseTemplate<SDerived> {};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:13:17