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

特定场景下如何从C++静态成员函数调用非静态成员函数

问题解决:静态成员函数调用非静态成员函数的编译错误

错误原因

静态成员函数func属于类本身而非类的实例,没有隐含的this指针;而非静态成员函数xupv必须依赖类的实例对象才能调用,直接在静态函数中调用会触发编译错误。同时,若将func改为非静态成员函数,由于非静态成员函数的签名隐含this指针,无法直接作为普通函数指针传递给QCDNUM::evolfg。

解决方案

通过给Local_类添加静态成员变量保存实例指针,让静态函数func能通过该指针调用非静态成员函数xupv,具体步骤如下:

  • 在Local_类中声明静态指针成员,用于存储当前实例的地址;
  • 在创建local对象后,将其地址赋值给该静态指针;
  • 在静态函数func中,通过静态指针调用xupv。

修改后的代码示例

#include <iostream>
#include <iomanip>
#include <cmath>
#include <fstream>
#include "QCDNUM/QCDNUM.h"
#include <boost/math/quadrature/trapezoidal.hpp>
#include <vector>

using boost::math::quadrature::trapezoidal;

using namespace std::complex_literals;
using std::cout;
using std::end;

double M = 932.17;
double B = 1.0 / 73.0;
double m_u = 162;
double m_d = 81;
double V = 4.0 / 3.0 * 3.14159 * pow(0.0056, 3);
double R = 0.0056;

auto f(double m, double n){

    class Local_
    {
    public:
      int a;
      int b;
      static Local_* instance; // 静态指针,保存当前实例地址

      auto xupv( double x )
      {
         auto z = [&](double E){
            auto a_1 = a*b*E;
            return a_1;
         };
         auto e = trapezoidal(z, x * M / 2.0, M / 2.0);
         auto d = pow(x, 2) * pow(M, 2) / 2.0;
         return e * d;
      };


      static auto func(int *ipdf, double *x)
      {
        int i = *ipdf;
        double xb = *x;
        double f = 0;
        if (i == 1)
            f = instance->xupv(xb); // 通过静态指针调用非静态成员函数
        // 其他分支保持不变
        return f;
      };
    } local;

    Local_::instance = &local; // 将当前实例地址赋值给静态指针

// -----------------------------------------------------------

    int ityp = 1, iord = 3, nfin = 0;                       // unpol, NLO, VFNS
    double as0 = 0.364, r20 = 2.0;                          // input alphas
    double xmin[] = {1.e-4, 1.e-3, 1.e-2, 1.e-1};           // x-grid
    int iwt[] = {1, 1, 1, 1}, ng = 4, nxin = 100, iosp = 3; // x-grid
    int nqin = 60;                                          // mu2-grid
    double qq[] = {1e0, 15}, wt[] = {1e0, 1e0};             // mu2-grid
    double q2c = 3, q2b = 25, q0 = 1;                       // thresholds, mu20
    double x = 1, q = 15, qmz2 = 8315.25, pdf[13];

    double def[] = // input flavour composition
        // tb  bb  cb  sb  ub  db   g   d   u   s   c   b   t
        {0., 0., 0., 0., 0., -1., 0., 1., 0., 0., 0., 0., 0., // 1=dval
         0., 0., 0., 0., -1., 0., 0., 0., 1., 0., 0., 0., 0., // 2=uval
         0., 0., 0., -1., 0., 0., 0., 0., 0., 1., 0., 0., 0., // 3=sval
         0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.,  // 4=dbar
         0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.,  // 5=ubar
         0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.,  // 6=sbar
         0., 0., -1., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., // 7=cval
         0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,  // 8=cbar
         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,  // 9=zero
         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,  // 10=zero
         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,  // 11=zero
         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.}; // 12=zero

    int nx, nq, id1, id2, nw, nfout, ierr;
    double eps;
    int lun = 6;
    std::string outfile = " ";

    QCDNUM::qcinit(lun, outfile);                    // initialize
    QCDNUM::gxmake(xmin, iwt, ng, nxin, nx, iosp);   // x-grid
    QCDNUM::gqmake(qq, wt, 2, nqin, nq);             // mu2-grid
    QCDNUM::wtfile(1, "../weights/unpolarised.wgt"); // calculate weights
    QCDNUM::setord(iord);                            // LO, NLO, NNLO
    QCDNUM::setalf(as0, r20);                        // input alphas
    int iqc = QCDNUM::iqfrmq(q2c);                   // charm threshold
    int iqb = QCDNUM::iqfrmq(q2b);                   // bottom threshold
    QCDNUM::setcbt(nfin, iqc, iqb, 999);             // thresholds in the VFNS
    int iq0 = QCDNUM::iqfrmq(q0);                    // start scale

    QCDNUM::evolfg(11, Local_::func, def, iq0, eps);           // 传递静态成员函数指针

    QCDNUM::allfxq(1, x, q, pdf, 0, 1);              // interpolate all pdf's
    auto res = (pow(2.0 / 3.0, 2)) * (pdf[8] + pdf[4]) + (pow(1.0 / 3, 2)) * (pdf[7] + pdf[5]) + (pow(1 / 3.0, 2)) * (pdf[9] + pdf[3]);
    cout << res << endl;
}

// 初始化局部类的静态成员变量
decltype(f(0,0))::Local_* decltype(f(0,0))::Local_::instance = nullptr;

int main()
{
    f(5, 6);
    return 0;
}

注意事项

  • 由于Local_是函数f内部的局部类,其静态成员变量的初始化需要在函数外部进行,这里使用decltype推导类型完成初始化;
  • 该方案适用于单线程场景,若涉及多线程,需要添加同步机制避免实例指针被并发修改;
  • 若QCDNUM::evolfg支持传递用户自定义上下文参数(如额外的void*参数),可以优先选择该方式传递实例指针,避免使用静态变量带来的全局状态问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:01:05