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是虚函数,不能改成静态的,想请教错误原因和解决办法。
我已经修改代码复现了和实际项目完全一致的错误,希望能定位问题。
错误原因分析
问题有两个核心点:
- const权限不匹配:
make_obj是const成员函数,内部创建的obj1实例中,owner指向的Child1对象是const的,但method1是非const成员函数,C++禁止通过const指针调用非const成员函数,这是直接触发报错的原因。 - 野指针问题:
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
相关产品推荐
相关产品推荐

