【问题标题】:C++ comparing pointers using multiple-inheritance with unknown base classC++ 使用多重继承比较指针与未知基类
【发布时间】:2016-05-27 17:24:55
【问题描述】:

我有两个 std::vectors 指向类 AB 的指针,我正在尝试创建一个从这些向量中删除对象的方法。此对象可能是也可能不是A 和/或B 的子类,并且不必是任何向量的元素。我试过以下代码:

void removeObject(void *object) {
    A *pa = static_cast<A*>(object);
    std::vector<A*>::iterator aPos = std::find(as.begin(), as.end(), pa);
    if (aPos != as.end())
        as.erase(aPos);
    B *pb = static_cast<B*>(object);
    std::vector<B*>::iterator bPos =  std::find(bs.begin(), bs.end(), pb);
    if (bPos != bs.end())
        bs.erase(bPos);
}

但是指针有不同的值,所以std::find 不起作用(或者说它有时起作用)。在阅读了Multiple inheritance pointer comparisonC++ pointer multi-inheritance fun 之后,我明白了原因,但在这两种情况下,建议的解决方案是将指针转换为*subclass。我的问题是:

  1. 如何检查两个指针​​是否指向同一个对象 不知道它的类型?
  2. 我的问题有更优雅的解决方案吗?

我是 C++ 新手,所以如果我完全误解了某些内容,请原谅...

【问题讨论】:

  • 我不相信语言本身有解决方案。您的解决方案可能会涉及约定...例如,您要以这种方式比较的所有对象都将继承自一个(接口)类,该类提供一个返回 void* 的单个虚函数,该虚函数由 @987654331 实现@ 然后比较从该调用中返回的指针。如果您是 Windows 程序员 - 这就像您总是通过首先为 IUnknown 执行 QueryInterface 然后比较这两个 IUnknown 指针来比较两个 COM 对象。
  • 请解释你的类层次结构。似乎 A 和 B 都需要通过一些公共基类来关联,这些基类将具有例如 for 形式的类型信息。枚举。在这种情况下,您可以将 void* 强制转换为该基类,并通过读取应该在创建类实例时设置的枚举来查找基础类型。可能还有其他一些棘手的解决方案,但我无法想出一个,尤其是多重继承变得更加棘手

标签: c++ pointers multiple-inheritance


【解决方案1】:

如果你的类是多态的(至少有一个虚函数),那么dynamic_cast&lt;void *&gt;() 将返回一个指向最派生对象开头的指针——所以即使你开始,它也总是会为同一个对象返回相同的答案从指向不相关基类的指针。

但是,如果您已经将指针转换为 void *,那就太迟了。最好只存储指向某个通用基类的指针。

【讨论】:

  • 我不知道(关于dynamic_cast&lt;void*&gt;,谢谢。
【解决方案2】:

void* 是 C++ 中的一个旧 C 概念,您知道您正在使用什么类型,因为这是模板编程的基础。为此,让我们将您的函数签名更改为:

template <typename T>
void removeObject(T* object);

从这里我们可以使用is_base_of来识别该类型是否是每个vectorvalue_type的元素的基:

if(is_base_of_v<T, decltype(as)::value_type>) {
    auto aPos = find(cbegin(as), cend(as), *static_cast<A*>(object));

    if(aPos != cend(as)) as.erase(aPos);
}

if(is_base_of_v<T, decltype(bs)::value_type>) {
    auto bPos = find(cbegin(bs), cend(bs), *static_cast<B*>(object));

    if(bPos != cend(bs)) bs.erase(bPos);
}

显然,如果object 是一个指向实际基类的指针,那么static_cast 将是完全非法的。我假设尽管object 是一个指向基类的指针,但它确实是static_cast 所指向的类型,否则我们需要回到绘图板。

【讨论】:

    猜你喜欢
    • 2012-06-30
    • 1970-01-01
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多