另一个 class 的 c++ 私有对象:初始化并使用它来调用 class 中的函数

c++ private object of another class: initialization and use it to call a function in that class

我有两个 classes AB,其中 class B 看起来像

B.h

class B
{
 public:
    B();
    virtual ~B();
    void eval(int a, int b);
 private:
    A* APointer;
};

相应地我有

B.cpp

B::B():APointer(NULL){}
B::~B(){}

void B::eval(int a, int b)
{
   if a == b
      {
      APointer->run(); // run() is a public method defined in class A
      }
}

那么 class A 就像:

A.h

#include "LuaBridge.h"
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
using namespace luabridge;

class LuaParser
{
  public:
    LuaParser(lua_State* L);
    virtual ~LuaParser();
    void run();

  private:
    LuaRef mRun;
    LuaRef mStop;
    lua_State* mL;
};

A.cpp

LuaParser::LuaParser(lua_State* L) :mRun(L),mStop(L),mL(L) {}
LuaParser::~LuaParser(){}

void LuaParser::run(){
std::cout<<"This project runs!"<<std::endl;
}

系统很复杂,实际上我在class C成员函数中调用了这个eval函数。在那个 class 中,我通过 B* BPointer 定义了一个私有成员 BPointer,在构造函数中我做了 C(B* BPointer = NULL),然后我在 class C 成员函数中简单地使用了 BPointer->eval(a,b)

在我的 main 代码中,我在 class B 中定义了一个指针,如 B* BPointer 我使用这个指针通过 [=31= 调用方法 B::eval ]

BPointer -> eval(a, b);

然而,当我 运行 它在 visual studio 中一步一步地执行时,在命令行 APointer->run(); 我注意到 this 指针是这样的:

Value: 0xcdcdcdcd{APointer=???}

当我尝试 运行 这个命令时,我得到了一个错误:

Access violation reading location 0xCDCDCDD1.

嗯...我不知道如何解决这个问题,我想知道的是:

  1. 整个想法(即在这个class的方法中使用私有对象调用另一个class的函数)是否可行?

  2. 如果这个想法可行,那我应该如何修改我的代码?

我们非常欢迎任何建议或想法!

您必须在 class B 的构造函数中使用一些真实对象初始化 APointer 数据成员。它应该如下所示,

B::B()
{
   this->APointer = new A();
}

B::~B()
{
  delete this->APointer;
  this->APointer = NULL;
}
...
...

int main()    
{
   B* BPointer = new B();

   int x = 5;
   int y = 5;

   BPointer->eval(x, y);
}

在您上面提到的代码中,APointer 被初始化为 NULL。我认为当 B::eval() 被执行时,它会导致一些未定义的行为。

如果你也能post class A的代码就更好了

0xcdcdcdcd

是已分配但尚未初始化内存的状态。您是否以适当的方式实例化了 BPointer?例如

BPointer = new B(); 

除此之外,您的 APointer 为 NULL,因此您不能调用任何方法,例如

APointer->run();

在构造类型 A 的对象并将其分配给 APointer 之前。

Is the whole idea (i.e. use a private object to call function of another class in a method of this class) feasible?

是的,这很常见。

If this idea is feasible, then how should I modify my code?

您需要了解对象和指针之间的区别。指针是内存区域的地址,甚至可能未分配。

这里有两个指针不指向任何分配的内存,因此没有对象的方法可以调用。

BPointer 是单元化的,它包含随机内存区域的地址(或调试版本中的幻数 0xcdcdcdcd),它可能包含任何属于或不属于你的东西。取消引用它是 undefined behavior。为避免这种情况,您应该创建 B 对象并将其指针分配给 BPointer:

B *BPointer = new B;

使用完BPointer后,您应该释放内存并通过调用

调用B的析构函数
delete BPointer;

APointer 是用 NULL 指针初始化的,这意味着它不指向任何内存区域。取消引用 NULL 也是未定义的行为。类似BPointer,应该用有效的对象指针初始化,稍后释放:

B::B() : APointer(new A(/* lua state pointer */ NULL)) {}
B::~B() { delete APointer; }

如果您不一定需要指针,我建议为 B 使用堆栈分配并将 A 存储为普通成员(而不是指针)。这样你就不需要为指针的初始化和删除而烦恼了。

B.h

class B
{
 public:
    B();
    void eval(int a, int b);
 private:
    A AObject;
};

B.cpp

B::B() : AObject(/* lua state pointer */ NULL) {}

void B::eval(int a, int b)
{
    if (a == b) 
    {
        AObject.run();
    }
}

main.cpp

// ...
B b;
b.eval()
// ...