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

c++ how to get a pointer to the current object in another class?

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

我有两个 类。我们将它们命名为A和B。A有很多成员变量和方法。 B 是一个结构,它有一个 shared_pointer 到一个类型 A 的对象。现在 A 有一个方法 returns 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) 为以下代码创建可执行文件,但在运行时我得到 "Segmentation fault (core dumped)":

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

我阅读了有关 std::enable_shared_from_this 的信息,但我无法弄清楚它是如何工作的,或者它是否对我有帮助。

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

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

据我所读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 必须由其他 std::shared_ptr 管理,然后才能调用 A::mymethod()。 IE。您必须像这样创建 A 对象:

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

然后你可以调用A::mymethod():

B b_obj = a_obj->mymethod();

编辑 2:

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

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

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

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

编辑: 在您编辑之后,第一个主题不再相关。我留下它是因为我在演示如何解决它的现场演示中使用了这段代码。

首先,导致转储的语句无法像您提供的那样编译:

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

因为instance.pointershared_ptr<C>C没有成员myvar

如果用 dynamic_pointer_cast<A>(instance.pointer)->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() 是常量,所以它认为 this 是指向常量的指针。要编译该语句,您必须删除 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(); 
...

而Cclass必须继承如下:

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

我的方法 class 必须初始化 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