C++如何设计接收函数指针数组的函数以实现ScalarField逐位置源项计算
实现方案
你可以在ScalarField类内部维护位置到源函数的稀疏映射,提前注册所有源点对应的函数,调用GetSource时无需额外传参,自动根据坐标匹配对应源函数即可,具体实现如下:
1. 核心思路
因为源是稀疏分布的,不需要为所有N个空间位置分配存储,仅用哈希表存储有源源的线性索引和对应函数指针即可,空间开销仅为O(n)。
2. 修改后的类实现
#include <vector> #include <unordered_map> // 源函数定义保持不变 double Source_1(double scalar) { /* 计算逻辑 */ } // ... double Source_n(double scalar) { /* 计算逻辑 */ } class ScalarField { public: // 原有构造函数、析构函数、CartesianToLinear、operator() 保持不变 size_t CartesianToLinear(const size_t i, const size_t j, const size_t k) { return i + dim_x_ * j + dim_x_ * dim_y_ * k; } double operator()(const size_t i, const size_t j, const size_t k) const { return scalar_[CartesianToLinear(i, j, k)]; } // 新增:注册指定位置对应的源函数 void RegisterSource(size_t i, size_t j, size_t k, double(*SourceFunc)(double)) { size_t linear_idx = CartesianToLinear(i, j, k); source_map_[linear_idx] = SourceFunc; } // 修改后的GetSource:自动匹配坐标对应的源函数 double GetSource(const size_t i, const size_t j, const size_t k) { size_t linear_idx = CartesianToLinear(i, j, k); auto iter = source_map_.find(linear_idx); if (iter != source_map_.end()) { // 匹配到源函数,传入当前位置标量值计算返回 return iter->second((*this)(i, j, k)); } // 无源源的位置返回默认值(可根据需求修改为其他值) return 0.0; } private: std::vector<double> scalar_{}; size_t dim_x_, dim_y_, dim_z_; // 新增:稀疏存储<线性索引, 源函数指针>的映射表 std::unordered_map<size_t, double(*)(double)> source_map_{}; };
3. 使用示例
// 初始化ScalarField对象 ScalarField field; // ... 省略dim_x_/dim_y_/dim_z_、scalar_的初始化逻辑 // 提前注册所有源点对应的函数 field.RegisterSource(2, 5, 7, Source_1); // 位置(2,5,7)使用Source_1 field.RegisterSource(10, 3, 9, Source_n); // 位置(10,3,9)使用Source_n // 调用时仅需传坐标,自动匹配对应源函数计算 double s1 = field.GetSource(2,5,7); double s2 = field.GetSource(10,3,9); double s3 = field.GetSource(1,1,1); // 无源源,返回0
进阶优化
如果你的源函数需要携带额外状态(比如固定强度系数、坐标相关参数),可以将函数指针替换为std::function<double(double)>,支持传入lambda、仿函数等更灵活的可调用对象,其他逻辑无需修改。
内容的提问来源于stack exchange,提问作者bhache
相关产品推荐
相关产品推荐

