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

C++实现接口时非法调用非静态成员函数问题求助

C++派生类调用非静态成员函数报错:非法调用非静态成员函数

我在C++中实现接口时,遇到了非法调用非静态成员函数的错误,场景是在派生类的内部结构体中调用基类的虚方法。以下是复现错误的代码:

头文件 ClassHeader.h

#include <vector>

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

namespace b
{
   struct mainObj
   {
      virtual ~mainObj(void) {}

      virtual double met(const std::vector<double>& vals) const = 0;
   };


   class Interface
   {
   public:
      Interface(size_t m, const std::vector<double>& tt);

   protected:
      struct OriginalObj;

      size_t _m;
      std::vector<double> _tt;

   private:
      virtual boost::shared_ptr<OriginalObj> make_obj(size_t M, const std::vector<double>& T) const = 0;
      virtual const std::vector<double> method1(size_t M, const std::vector<double>& vals) = 0;

   };

   namespace a {
      class Child1 : public Interface
      {
      public:
         Child1(size_t m, const std::vector<double>& tt);

      private:
         struct obj1;
         boost::shared_ptr<OriginalObj> make_obj(size_t M, const std::vector<double>& T) const override;

         const std::vector<double> method1(size_t M, const std::vector<double>& vals) override;

      };
   } // namespace a

} // namespace b

实现文件 ClassHeader.cpp

#include "ClassHeader.h"

namespace b
{

Interface::Interface(size_t m, const std::vector<double>& tt)
 :  _m(m), _tt(tt) {}

struct Interface::OriginalObj : public mainObj {
   OriginalObj(size_t n, const std::vector<double>& t)
      : _n(n),_t(t) {}

   size_t _n;
   std::vector<double> _t;
};

namespace a {

   const std::vector<double> Child1::method1(size_t M, const std::vector<double>& vals)
   {
      return { static_cast<double>(M), vals[0] };
   }

   struct Child1::obj1 : public Interface::OriginalObj
   {
      using Interface::OriginalObj::OriginalObj;

      Child1* owner;

      double met(const std::vector<double>& vals) const override
      {
         std::vector<double> c = owner->method1(_n, vals);
         return c[0];
      }
   };

   Child1::Child1(size_t m, const std::vector<double>& tt)
      :Interface(m, tt)
   {
      obj1 o1(m, tt);
      o1.owner = this;
   }

   auto Child1::make_obj(size_t M, const std::vector<double>& T) const
      -> boost::shared_ptr<OriginalObj>
   {
      return boost::shared_ptr<OriginalObj>{new Child1::obj1(M, T)};
   }

} //namespace a
} // namespace b

我明白通常需要通过对象调用非静态成员函数,但误以为在类内部调用会隐含对象实例。另外method1是虚函数,不能改成静态的,想请教错误原因和解决办法。

我已经修改代码复现了和实际项目完全一致的错误,希望能定位问题。


错误原因分析

问题有两个核心点:

  1. const权限不匹配:make_obj是const成员函数,内部创建的obj1实例中,owner指向的Child1对象是const的,但method1是非const成员函数,C++禁止通过const指针调用非const成员函数,这是直接触发报错的原因。
  2. 野指针问题:Child1构造函数里创建的obj1 o1是局部对象,赋值o1.owner = this后会被销毁,而make_obj新创建的obj1实例的owner成员是未初始化的野指针,调用owner->method1会导致未定义行为。

解决办法

1. 修复const权限不匹配

把method1声明为const成员函数(因为它仅返回计算结果,未修改对象状态):

  • 在Interface类中修改:
    virtual const std::vector<double> method1(size_t M, const std::vector<double>& vals) const = 0;
    
  • 在Child1类中修改:
    const std::vector<double> method1(size_t M, const std::vector<double>& vals) const override;
    
  • 对应的实现也加上const:
    const std::vector<double> Child1::method1(size_t M, const std::vector<double>& vals) const
    {
        return { static_cast<double>(M), vals[0] };
    }
    

2. 正确初始化obj1的owner成员

放弃在Child1构造函数中操作局部obj1,改为在make_obj创建obj1时直接初始化owner:

  • 修改obj1的定义,添加带owner参数的构造函数:
    struct Child1::obj1 : public Interface::OriginalObj
    {
        obj1(size_t n, const std::vector<double>& t, Child1* owner_ptr)
            : OriginalObj(n, t), owner(owner_ptr) {}
    
        Child1* owner;
    
        double met(const std::vector<double>& vals) const override
        {
            std::vector<double> c = owner->method1(_n, vals);
            return c[0];
        }
    };
    
  • 修改make_obj的实现,通过const_cast转换const指针(因为method1已改为const,该转换安全):
    auto Child1::make_obj(size_t M, const std::vector<double>& T) const
        -> boost::shared_ptr<OriginalObj>
    {
        return boost::make_shared<Child1::obj1>(M, T, const_cast<Child1*>(this));
    }
    

3. 额外优化

使用boost::make_shared替代直接new对象,更符合RAII规范,避免内存泄漏风险。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 22:53:13