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

时间:2015-11-26 07:27:24

标签: c++ class private

我有两个课程AB,其中课程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
      }
}

然后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;
}

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

在我的main代码中,我在类B中定义一个指针,如B* BPointer,我使用此指针通过

调用方法B::eval
BPointer -> eval(a, b);

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

Value: 0xcdcdcdcd{APointer=???}

当我尝试运行此命令时,出现错误:

Access violation reading location 0xCDCDCDD1.

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

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

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

  3. 任何建议或想法都非常受欢迎!

3 个答案:

答案 0 :(得分:0)

你必须在类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()时会导致一些未定义的行为。

如果您还可以发布A类代码,那将是件好事。

答案 1 :(得分:0)

0xcdcdcdcd

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

BPointer = new B(); 

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

APointer->run();
在构造A类型的对象并将其分配给APointer之前

答案 2 :(得分:0)

  

是整个想法(即使用私有对象来调用函数)   这个方法中的另一个类可行吗?

是的,这很常见。

  

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

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

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

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()
// ...