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.pointer
是shared_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_this
:instance.pointer
的使用计数将为 1,因为在那一刻只有一个引用新创建的共享对象。
还是要引用原始对象?
然后您必须将语句更改为:
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
然后一切正常。
又是一个问题,但我不知道如何简短地解释这种情况:
我有两个 类。我们将它们命名为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.pointer
是shared_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_this
:instance.pointer
的使用计数将为 1,因为在那一刻只有一个引用新创建的共享对象。
还是要引用原始对象?
然后您必须将语句更改为:
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
然后一切正常。