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<A>(...)
代替了obj(new A);
。有问题吗?
糟糕。方法A::mymethod()
不能是const
,因为shared_from_this()
也不是const
。这是有道理的(也许?),因为shared_from_this()
需要更改内部持有的引用计数器。
可以使用std::make_shared<A>(...)
,只要由std::shared_ptr
管理即可。
我删除了所有的 const 标志,但仍然有相同的错误消息告诉“'std::enable_shared_from_this' is an inaccessible base of 'A'”【参考方案2】:
初步问题:如何向下转换以访问 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,因为此时只有一个对新创建的共享对象的引用。
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 ++如何获取指向另一个类中的当前对象的指针?的主要内容,如果未能解决你的问题,请参考以下文章