【问题标题】:How can I match Base* against a list of Derived*, from within Base destructor?如何从 Base 析构函数中将 Base* 与 Derived* 列表匹配?
【发布时间】:2016-09-28 02:24:14
【问题描述】:

我有两个班级,BaseDerived。我有一个存储Derived* 指针列表的容器。

有一个信号/槽机制,它在 Base 对象被销毁时发出一个信号,此时我们在 ~Base 析构函数中,因此 RTTI 不能用于将 Base* 转换为 Derived*(这是使用 Qt,但问题不是 Qt 特定的)

该信号连接到管理指针容器的插槽。你可能已经猜到了,我想检查其对象被销毁的Base*指针是否对应存储在容器内的Derived*指针,如果是,则将其从容器中移除。

我知道有许多替代设计,例如不使用QObject::destroyed() 信号,或者存储QObject* 列表而不是Derived*。但出于许多实际原因,我想使用那个。

这意味着,我想将基指针转换为派生指针,不是为了取消引用,而是为了取消跟踪指针,并且我希望它被定义为无论子类树是什么(包括多重继承、虚函数.. .).

我可以为此使用 static_cast 吗?

谢谢!

【问题讨论】:

  • 糟糕 - 感谢您的关注
  • 嗯,您可以使用static_cast,但您必须确保类型正确。
  • @DavidHaim :正如我所说,我知道还有其他可能的设计,但这里的问题是具体的。我无法在此处修改基类(即 QObject Qt 基类)
  • @πάνταῥεῖ:你能解释一下吗? static_cast 的潜在问题正是我所缺少的。
  • @DavidHaim :然后我必须重写 Qt。基类,信号槽机制,都是框架的核心特性。

标签: c++ pointers casting derived-class rtti


【解决方案1】:

您可以将static_cast 用于容器的每个元素的base 类型,并将其与*base ptr 进行比较。这样你就可以找到对象了。

class Base;
class Derived;
std::vector<Derived*> arrDerived;

void Remove(Base* pBase);

class Base
{
public:
    ~Base()
    {
        Remove(this);
    }
};

class Derived : public Base
{

};

void Remove(Base* pBase)
{
    for (Derived* pDerived : arrDerived)
    {
        //if (static_cast<Base*>(pDerived) == pBase) same as
        if (pDerived == pBase)
        {
            //you found it!!!!
            return;
        }
    }
}

当您执行static_cast&lt;Base*&gt;(Derived) 时,编译器只是将ptr 移动了一些const 内存量(因此它指向基类)。因此,此操作与实际内存状态和safe 无关。

编辑:正如@a​​lain 提到的,您可以在没有static_cast 的情况下进行比较-它将自动执行。

【讨论】:

  • 感谢您的回答。在哪些情况下做相反的事情(向上转换 ptr)会是未定义的行为?
  • 我已经编辑了答案。即使您销毁所有对象,向上转换也会起作用 :) 事情是 upcastinginvalid pointer 会给 invalid pointer。但是对于搜索它并没有什么影响。
【解决方案2】:

在评论中,您写道:

将转换指针与表比较 Derived* 用于删除的指针 它。当然我不会取消对强制转换指针的引用。

在这种情况下,根本不需要强制转换,你可以直接比较你的指针:

Base* base;
Derived* derived;
if(base == derived) {
}

【讨论】:

  • 这是有道理的。 static_cast 自动执行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 2022-01-21
  • 1970-01-01
  • 2021-10-09
  • 1970-01-01
相关资源
最近更新 更多