将成员函数指针传入模板:C++多态场景下的实现疑问
解决你的OOP模板函数与成员函数指针问题
我来帮你搞定这个问题~你的核心需求是通过模板函数灵活选择派生类(D1/D2)以及它们的成员函数(add/multi),这里的关键是正确传递成员函数指针到模板中,同时先修正代码里的几个基础语法错误。
第一步:修正类定义的语法问题
你的原始代码里有几个编译不过的问题,先调整一下:
- 基类
Base的data成员是private,派生类无法访问,改成protected; - 基类的构造函数要设为
public,否则派生类没法调用; - 继承语法错误:
class D1::public Base要改成class D1 : public Base; - 建议加上
override关键字明确重写虚函数,增强可读性。
修正后的类代码如下:
#include <iostream> using namespace std; class Base { protected: double data; public: Base(double d) : data(d) {}; virtual double add() = 0; virtual double multi() = 0; }; class D1 : public Base { public: D1(double d) : Base(d) {}; double add() override { return data + 1; }; double multi() override { return data * 2; }; }; class D2 : public Base { public: D2(double d) : Base(d) {}; double add() override { return data + 3; }; double multi() override { return data * 4; }; };
第二步:实现灵活的模板函数
这里提供两种常用的实现方式,都能满足你的需求:
方式一:将成员函数指针作为模板参数(编译期绑定)
这种方式把成员函数指针作为模板的非类型参数,编译期确定调用哪个函数,性能最优:
// 模板参数:派生类T,以及T中返回double、无参数的成员函数指针 template <typename T, double (T::*Func)()> void testFun(double num) { T tmp(num); // 调用成员函数指针的语法:对象.*函数指针,注意括号不能少 cout << (tmp.*Func)() << endl; } // 调用示例 int main() { testFun<D1, &D1::add>(5); // 输出6 testFun<D1, &D1::multi>(5); // 输出10 testFun<D2, &D2::add>(5); // 输出8 testFun<D2, &D2::multi>(5); // 输出20 return 0; }
方式二:将成员函数指针作为函数参数(运行期灵活切换)
如果你需要在运行时动态选择成员函数,可以把函数指针作为普通函数参数传入:
template <typename T> void testFun(double num, double (T::*Func)()) { T tmp(num); cout << (tmp.*Func)() << endl; } // 调用示例 int main() { testFun<D1>(5, &D1::add); testFun<D2>(5, &D2::multi); // 甚至可以动态切换函数,比如: double (D1::*selectedFunc)() = &D1::add; testFun<D1>(5, selectedFunc); selectedFunc = &D1::multi; testFun<D1>(5, selectedFunc); return 0; }
关于纯虚函数的疑问
你提到有人说函数指针不适用于纯虚函数——其实这个担心是多余的:我们并没有直接使用基类Base的纯虚函数指针(它本身没有实现,确实没法调用),而是使用派生类已经实现的成员函数指针,这完全是合法的,和普通成员函数指针用法一致。
内容的提问来源于stack exchange,提问作者HGWantToLearn
相关产品推荐
相关产品推荐

