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

C++公有继承中基类公有成员函数为何变为私有?

问题描述

基类Potential包含public成员函数r()、l()、s()、j()等,通过public继承的派生类HammachePotential对象调用这些函数时,编译器报错称对应的派生类私有成员不可访问,但Mr()函数无此问题。

基类代码

#define POTENTIALS_HPP

#include <cmath>
#include "Matrix.hpp"
#include "Physics_constants.hpp"
#include "PotentialData.hpp"

class Potential {
public:
    Potential() {}
    Potential(int l, int s, int j, double Mmu) : m_l(l), m_s(s), m_j(j),
        m_Mmu(Mmu){}
    virtual void setL(int) = 0;
    virtual void setS(int) = 0;
    virtual void setJ(int) = 0;
    virtual void setR(double) = 0;
    ushort l() const {return m_l;}
    ushort s() const {return m_s;}
    ushort j() const {return m_j;}
    double r() const {return m_r;}
    double Mr() const {return m_Mmu;}
    ~Potential() {}

    virtual Matrix<double> operator () () const = 0;
    virtual Matrix<double> operator () (double) = 0;
    Matrix<double> Veff() const {
        if (m_l==0 || m_r == 0)
            return (*this)();
        Matrix<double> p = (*this)();
        Matrix<double> L(p.cols());
        for (uint i=0; i<L.cols(); i++)
            L[i][i] = (m_l+2*i)*(m_l+2*i+1);
        L = L*(pow(Physics::Nuclear::hc,2)/(2*m_Mmu*m_r*m_r));
        std::cout << m_Mmu << "  " << m_r << std::endl;
        std::cout << p-L << std::endl;
        abort();
        return p-L;
    }
    Matrix<double> Veff(double r) {
        setR(r);
        return Veff();
    }

protected:
    ushort m_l;
    ushort m_s;
    ushort m_j;
    double m_r;
    double m_Mmu;
};

#endif // POTENTIALS_HPP

派生类代码

#ifndef ALPHAD_POTENTIAL_HAMMACHE_HPP
#define ALPHAD_POTENTIAL_HAMMACHE_HPP

#include "Physics_constants.hpp"
#include "Potentials.hpp"
#include <cmath>

class HammachePotential : public Potential {
public:
    HammachePotential() { m_s = 1; m_Mmu = PotentialData::Hammache::Mr;}
    HammachePotential(int l, int j) : Potential(l,1,j,PotentialData::Hammache::Mr) {
        if (l==0)
            V0 = 60.712;
        else
            V0 = 56.7;
        setLS2(l,s,j);
    }

    void setS(int) override {m_s=1;}

    void setL(int l) override {
        this->l = l;

        if (l==0)
            V0 = 60.712;
        else
            V0 = 56.7;
        setLS2(l,s,j);
    }
    void setJ(int j) override {
        this->j = j;
        setLS2(l,s,j);
    }
    void setR(double r) override {
        if (r==0)
            return;
        this->r = r;

        EXPR = expr(r);
        EXPRM1 = exprm1(EXPR);
    }

    std::tuple<int,int,int,double> getInfo() const {
        return {l,s,j,r};
    }

    double getVcDepth() const {
        return V0;
    }


    Matrix<double> operator () () const {
        if (r==0)
            return Matrix<double>(1);
        double Vc = -V0*EXPRM1;
        double Ve = Vem(r);
        double Vso= VSO*EXPR*std::pow(EXPRM1,2)/r;
        Matrix<double> ret(1);
        ret[0][0] = Vc+Ve+Vso;
        return ret;
    }

    Matrix<double> operator () (double r) {
        if (r==0)
            return Matrix<double>(1);
        setR(r);
        double Vc = -V0*EXPRM1;
        double Ve = Vem(r);
        double Vso= VSO*EXPR*std::pow(EXPRM1,2)/r;
        Matrix<double> ret(1);
        ret[0][0] = Vc+Ve+Vso;
        return ret;
    }



private:
    const double a =    0.65; //fm
    const double r0 =   1.25; //fm
    const double R =    r0*std::pow(6.,1./3); //fm
    const double l2 =   4.; //fm^2 -> lambda^2
    int l = 0;
    const int s = 1;
    int j = 1;
    int LS2;
    double V0;
    const double V1 = 2.4; //MeV
    const double coul = 2*Physics::alpha*Physics::Nuclear::hc;
    const double VSOfac0 = -V1*l2/a;
    double VSO;
    double r;
    double EXPR;
    double EXPRM1;

private:
    inline void setLS2(int l, int s, int j) {
        LS2 = j*(j+1) - l*(l+1) - s*(s+1);
        VSO = VSOfac0*LS2;
    }
    inline double Vem(double r) const {
        if (r<=R)
            return coul*(3-std::pow(r/R,2))/(2*R);
        else
            return coul/r;
    }
    inline double expr(double r) const {
        return std::exp( (r-R)/a );
    }
    inline double exprm1 (double expr) const {
        return 1.0/(1.0 + expr);
    }
};
#endif // ALPHAD_POTENTIAL_HAMMACHE_HPP

编译错误

...main.cpp:184: error: ‘double HammachePotential::r’ is private within this context
...main.cpp:184:30: error: ‘double HammachePotential::r’ is private within this context
  184 |             std::cout << pot.r() << std::endl;
      |                              ^

l()、s()、j()方法调用时会出现同类错误,仅Mr()无报错。


问题原因与解决方案

问题根源

派生类HammachePotential中定义了私有成员变量l、s、j、r,这些名字和基类Potential的public成员函数名完全同名。在C++中,同一作用域内的同名实体(无论变量还是函数)会触发名字隐藏:派生类的变量名会覆盖基类的同名函数名,导致调用pot.r()时,编译器误将其解析为访问派生类的私有成员变量r,而非基类的public成员函数r()。

而Mr()无报错,是因为派生类中没有定义同名变量,编译器能正常找到基类的Mr()函数。

另外,派生类的设计存在冗余:基类已通过protected权限开放m_l、m_s、m_j、m_r成员,派生类无需重新定义一套私有变量,直接复用基类成员即可。

解决方案

删除派生类中冗余的私有成员变量l、s、j、r,直接使用基类的protected成员,并修改派生类成员函数的实现逻辑:

修改后的派生类关键代码片段

class HammachePotential : public Potential {
public:
    HammachePotential() { m_s = 1; m_Mmu = PotentialData::Hammache::Mr;}
    HammachePotential(int l, int j) : Potential(l,1,j,PotentialData::Hammache::Mr) {
        if (l==0)
            V0 = 60.712;
        else
            V0 = 56.7;
        setLS2(m_l, m_s, m_j); // 使用基类成员
    }

    void setS(int) override {m_s=1;}

    void setL(int l) override {
        m_l = l; // 赋值给基类的m_l
        if (l==0)
            V0 = 60.712;
        else
            V0 = 56.7;
        setLS2(m_l, m_s, m_j);
    }
    void setJ(int j) override {
        m_j = j; // 赋值给基类的m_j
        setLS2(m_l, m_s, m_j);
    }
    void setR(double r) override {
        if (r==0)
            return;
        m_r = r; // 赋值给基类的m_r
        EXPR = expr(m_r);
        EXPRM1 = exprm1(EXPR);
    }

    std::tuple<int,int,int,double> getInfo() const {
        return {m_l, m_s, m_j, m_r}; // 返回基类成员
    }

    Matrix<double> operator () () const {
        if (m_r==0)
            return Matrix<double>(1);
        double Vc = -V0*EXPRM1;
        double Ve = Vem(m_r);
        double Vso= VSO*EXPR*std::pow(EXPRM1,2)/m_r;
        Matrix<double> ret(1);
        ret[0][0] = Vc+Ve+Vso;
        return ret;
    }

private:
    // 删除原有的int l、const int s、int j、double r成员
    const double a =    0.65; //fm
    const double r0 =   1.25; //fm
    const double R =    r0*std::pow(6.,1./3); //fm
    const double l2 =   4.; //fm^2 -> lambda^2
    int LS2;
    double V0;
    const double V1 = 2.4; //MeV
    const double coul = 2*Physics::alpha*Physics::Nuclear::hc;
    const double VSOfac0 = -V1*l2/a;
    double VSO;
    double EXPR;
    double EXPRM1;

    inline void setLS2(int l, int s, int j) {
        LS2 = j*(j+1) - l*(l+1) - s*(s+1);
        VSO = VSOfac0*LS2;
    }
    // 其余私有函数保持不变
};

修改说明

  1. 删除派生类中与基类函数同名的私有变量l、s、j、r,消除名字冲突。
  2. 所有原本操作派生类私有变量的逻辑,改为操作基类的protected成员m_l、m_s、m_j、m_r。
  3. 基类的l()、s()、j()、r()函数会正常返回基类成员的值,调用不再触发权限错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 16:07:02