非法调用非静态成员函数 – C++

huangapple go评论79阅读模式
英文:

Illegal call of non-static member function - 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

我知道我在没有在对象上调用它的情况下使用它(例如 c1.method1(...)),但我认为由于它是一个类方法,这在某种程度上是暗示的。我面临的另一个问题是,我无法将该方法设为静态,因为它是虚拟的。

请问有谁能帮我理解我做错了什么以及如何解决这个问题吗?

提前感谢!


我更改了代码以重现错误。现在我在与实际代码中完全相同的位置遇到了完全相同的错误。希望这能帮到您找出我做错了什么。

再次感谢!

英文:

I'm trying to implement an interface in C++ but I get stuck on the problem in the title when I try to use some methods within the derived classes.

The idea of the code is as follows.

// ClassHeader.h
#include &lt;vector&gt;
#include &lt;boost/shared_ptr.hpp&gt;
#include &lt;boost/make_shared.hpp&gt;
namespace b
{
struct mainObj
{
virtual ~mainObj(void) {}
virtual double met(const std::vector&lt;double&gt;&amp; vals) const = 0;
};
class Interface
{
public:
Interface(size_t m, const std::vector&lt;double&gt;&amp; tt);
protected:
struct OriginalObj;
size_t _m;
std::vector&lt;double&gt; _tt;
private:
virtual boost::shared_ptr&lt;OriginalObj&gt; make_obj(size_t M, const std::vector&lt;double&gt;&amp; T) const = 0;
virtual const std::vector&lt;double&gt; method1(size_t M, const std::vector&lt;double&gt;&amp; vals) = 0;
};
namespace a {
class Child1 : public Interface
{
public:
// inherit constructor
// using Interface::Interface;
Child1(size_t m, const std::vector&lt;double&gt;&amp; tt);
private:
struct obj1;
boost::shared_ptr&lt;OriginalObj&gt; make_obj(size_t M, const std::vector&lt;double&gt;&amp; T) const override;
const std::vector&lt;double&gt; method1(size_t M, const std::vector&lt;double&gt;&amp; vals) override;
};
} // namespace a
} // namespace b
// ClassHeader.cpp
#include &quot;ClassHeader.h&quot;
namespace b
{
Interface::Interface(size_t m, const std::vector&lt;double&gt;&amp; tt)
:  _m(m), _tt(tt) {}
struct Interface::OriginalObj : public mainObj {
OriginalObj(size_t n, const std::vector&lt;double&gt;&amp; t)
: _n(n),_t(t) {}
size_t _n;
std::vector&lt;double&gt; _t;
};
namespace a {
const std::vector&lt;double&gt; Child1::method1(size_t M, const std::vector&lt;double&gt;&amp; vals)
{
return { static_cast&lt;double&gt;(M), vals[0] };
}
struct Child1::obj1 : public Interface::OriginalObj
{
// inherit constructor
using Interface::OriginalObj::OriginalObj;
Child1* owner;
double met(const std::vector&lt;double&gt;&amp; vals) const override
{
std::vector&lt;double&gt; c = owner-&gt;method1(_n, vals);
return c[0];
}
};
Child1::Child1(size_t m, const std::vector&lt;double&gt;&amp; tt)
:Interface(m, tt)
{
obj1 o1(m, tt); //new construction of o1
o1.owner = this; // does this initialize all the members as this?
}
auto Child1::make_obj(size_t M, const std::vector&lt;double&gt;&amp; T) const
-&gt; boost::shared_ptr&lt;OriginalObj&gt;
{
//return boost::make_shared&lt;OriginalObj&gt;(M, T);
return boost::shared_ptr&lt;OriginalObj&gt;{new Child1::obj1(M, T)};
}
} //namespace a
} // namespace b

I know I'm using it without calling it on the object (e.g. c1.method1(...)), but I thought that since it was a class method it was somehow implied. Another issue I'm facing is that I cannot make the method static because it is virtual.

Can anyone please help me understand what I'm doing wrong and how I can solve the problem?

Thanks in advance!


I changed the code to reproduce the error. now I get the exact same error as in my actual code, in the same exact place. Hope this can help you find what I'm doing wrong.

Thanks again

答案1

得分: 1

obj1 没有默认构造函数。这是因为它继承自定义了非默认构造函数的 OriginalObj,使得默认构造函数不存在(或已删除):

struct Interface::OriginalObj : public mainObj {
   OriginalObj(size_t n, const std::vector&lt;double&gt;&amp; t)
// ...
}
struct Child1::obj1 : public Interface::OriginalObj {
// ...
}

简单地定义 OriginalObj() = default; 可以解决这个问题,并将你带入下一个挑战,即 boost::make_shared&lt;OriginalObj&gt;(M, T); 试图构造一个抽象类的对象(met() 是纯虚函数)。你需要构造一个实际的 obj1,它可以被强制转换为 OriginalObj

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

完整演示: http://coliru.stacked-crooked.com/a/a24e42e600a92736

英文:

obj1 does not have a default constructor. This is because it inherits from OriginalObj that defines a non-default constructor, rendering the defaulted default constructor non-existant (or deleted):

struct Interface::OriginalObj : public mainObj {
OriginalObj(size_t n, const std::vector&lt;double&gt;&amp; t)
// ...
}
struct Child1::obj1 : public Interface::OriginalObj {
// ...
}

Simply defining OriginalObj() = default; fixes that problem and set you up to the next challenge, being boost::make_shared&lt;OriginalObj&gt;(M, T); tries to construct an object of an abstract class (met() is pure virtual). You need to construct an actual obj1 which can be cast into an OriginalObj:

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

Full demo: http://coliru.stacked-crooked.com/a/a24e42e600a92736

huangapple
  • 本文由 发表于 2023年7月10日 15:30:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76651580.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定