c ++如何获取指向另一个类中的当前对象的指针?

Posted

技术标签:

【中文标题】c ++如何获取指向另一个类中的当前对象的指针?【英文标题】:c++ how to get a pointer to the current object in another class? 【发布时间】:2015-08-11 21:53:49 【问题描述】:

又是一个格式错误的问题,但我不知道如何简短地解释这种情况:

我有两节课。我们将它们命名为 A 和 B。A 有很多成员变量和方法。 B 是一个结构,它有一个指向 A 类型对象的 shared_pointer。现在 A 有一个返回 B 实例的方法(带有指向 A 的当前实例的指针)。

我的问题是,A 是 C 的子类。C 具有与上述纯虚拟相同的方法。代码如下所示:

class C 
public:
  virtual B mymethod() const =0;
  virtual int getMyvar() const =0;
;

class A : public C 
public:
  B mymethod() const override;
  int getMyvar() const override;   //outputs myvar
private:
  int myvar;
;

struct B 
  std::shared_ptr<C> pointer;
;

B A::mymethod() const 
  B instance;
  instance.pointer = std::make_shared<A>(*this);   //is this wrong?
  return instance;

我的编译器 (gcc 4.8.2) 为以下代码创建可执行文件,但在运行时我得到“分段错误(核心转储)”:

void AnotherClass::something() const 
  A object;
  B instance = object.mymethod();
  std::cout << instance.pointer->getMyvar();   //dumps the core womehow?

我读到了std::enable_shared_from_this,但我不知道它是如何工作的,或者它是否对我有帮助。

为什么我会收到错误消息,我该如何解决这个问题?

【问题讨论】:

object.mymethod(); // 你缺少函数调用 是的,哈哈... =D 不,这是一个简单的例子。我的脚本太复杂而无法发布,但这个例子很好地解释了它。在我的情况下,我无法到达原始对象... =( 好的,抱歉,编辑了XD 刚刚忘记了,但是错误还在=( 我无法重现您的问题。您能否发布一个显示错误的完整示例? myvar 不在 C 中,即使在 A 中也无法访问。 【参考方案1】:

从我读到的in the manual,你做到了:

class A : public C, std::enable_shared_from_this<A> 
public:
  B mymethod() override; // Notice the lack of const
private:
  int myvar;
;

然后:

B A::mymethod() 
  B instance;
  instance.pointer = shared_from_this();   // this should be right
  return instance;

像这样,std::shared_ptr 对同一个 A 对象的所有实例将共享同一个引用计数器,并且只有在必须销毁时才会销毁。

编辑:

另外,请注意,您的对象 A 必须由其他一些 std::shared_ptr 管理,然后才能调用 A::mymethod()。 IE。您必须像这样创建 A 对象:

std::shared_ptr<A> a_obj(new A);

那你可以拨打A::mymethod():

B b_obj = a_obj->mymethod();

EDIT2:

方法A::mymethod()(因此,C::mymethod())不能是const才能调用非const方法shared_from_this()

【讨论】:

编译器告诉我“std::enable_shared_from_this is an inaccessible base of A”当我编译这个......? o.O 我用std::make_shared&lt;A&gt;(...)代替了obj(new A);。有问题吗? 糟糕。方法A::mymethod() 不能是const,因为shared_from_this() 也不是const。这是有道理的(也许?),因为shared_from_this() 需要更改内部持有的引用计数器。 可以使用std::make_shared&lt;A&gt;(...),只要由std::shared_ptr管理即可。 我删除了所有的 const 标志,但仍然有相同的错误消息告诉“'std::enable_shared_from_this' is an inaccessible base of 'A'”【参考方案2】:

初步问题:如何向下转换以访问 myvar ?

编辑:编辑后,第一个主题不再相关。我离开它是因为我在现场演示中使用了这段代码来说明如何解决它。

首先,导致转储的语句无法按照您给出的编译:

std::cout << instance.pointer->myvar; 

因为instance.pointershared_ptr&lt;C&gt;C 没有成员myvar

如果使用dynamic_pointer_cast&lt;A&gt;(instance.pointer)-&gt;myvar 正确向下转换(假设AnotherClass 是朋友),它可以工作。

您的共享指针克隆了:这是您的意图吗?

此声明:

instance.pointer = std::make_shared<A>(*this);   //is this wrong? PERHAP'S !?

*this创建一个通过复制构造获得的克隆对象。所以你不引用原始对象A,因此你不需要std::enable_shared_from_thisinstance.pointer 的使用计数将为1,因为此时只有一个对新创建的共享对象的引用。

Live demo

还是要它引用原始对象?

然后您必须将语句更改为:

instance.pointer = std::shared_ptr<A>(this);   //better ?

但这不会编译,因为 mymethod() 是 const,所以它认为 this 是指向 const 的指针。要编译该语句,您必须删除 mymethod() 的常量或将常量添加到 B 的指针。

然后就可以了。 B 的共享指针的使用计数仍然为 1,这又可以了。但是一旦这个 shared_ptr 超出范围,使用计数为 0 并且 shared_ptr 的析构函数将尝试删除该对象。因为它最初是一个本地对象(在堆栈上),所以这会导致运行时错误。

最终方法

由于你想要共享指向你的对象的指针,AnotherClass 的代码应该是这样的:

shared_ptr<C> pobject(new A);  // create the object from the free store
B instance = pobject->mymethod(); 
...

并且C类必须继承如下:

class C : public std::enable_shared_from_this<C> 
...

并且我的方法类必须初始化它返回的shared_pointer,如下所示:

//instance.pointer = std::shared_ptr<A>(this);    // no, don't do no longer !! 
instance.pointer = shared_from_this();  //<===== RETURN A POINTER TO SELF

然后一切正常。

Live demo

【讨论】:

【参考方案3】:

在我看来,当您的对象超出范围时会出现内存错误。 当您创建对象 A 然后使用 this 指针创建 shared_ptr 时,您的计数器将是 1 而不是 2(如您所料)。所以 A 将被销毁两次,而不是一次。 一个更正确的方法是创建类 A 作为 shared_ptr 并用它初始化类 B 中的指针(不在类 A 内)。这样,计数器将按照您的预期递增,并且 A 只会被删除一次。

【讨论】:

事实上,当 shared_ptr 试图删除一个本地对象(即不是用 new 创建的)时,就会发生运行时错误。概念证明here. 这可能取决于您的对象超出范围的顺序。如果 B 在 A 之前超出范围,则 A 将导致堆栈损坏。【参考方案4】:

您要共享的类需要从 enable_share_from_this 继承。 然后你可以调用 share_from_this 来获取你所在类的共享指针。

如果您只是尝试 make_shared,您只需创建一个单独的所有权组,这意味着有两件事会尝试删除您的对象。这将是您的段错误的原因。

【讨论】:

以上是关于c ++如何获取指向另一个类中的当前对象的指针?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用方法更改指针?

在目标 C 中引用另一个类中的实例化对象

C语言如何声明一个返回函数指针的函数?

Python中类和对象在内存中是如何保存?

c语言如何将两个变量关联起来

objective-c 中如何在一个函数中调用自己类中的另外一个函数