【问题标题】:C++ implementing object equality with multiple levels of iheritanceC++ 实现具有多级继承的对象相等性
【发布时间】:2019-08-30 09:19:57
【问题描述】:

我需要为具有多个继承级别的多个对象实现一个 isEqual 方法。出于这个原因,我决定不创建接口,因为该方法不是纯虚拟的,而只是我以后可以用作标记的类。

这些类实现了一个方法 isEqual。由于我需要定义默认行为,因此这些方法不是纯虚拟的。

class A_Interface {
    virtual isEqual(shared_ptr<A_Interface> obj);
    ...
    virtual otherMethod1();
}


class B_Interface : public virtual A_Interface {
    virtual isEqual(shared_ptr<B_Interface> obj);
    ...
    virtual otherMethod2();
}


class C_Interface : public virtual B_Interface {
    virtual isEqual(shared_ptr<C_Interface> obj);
    ...
    virtual otherMethod3();
}

每个类都实现了它自己的上面提到的“类接口”标签类,并像这样从父类继承:

class A : public virtual A_interface;
{
    isEqual(shared_ptr<A_Interface> obj){
    ...
    }
};



class B : public virtual A, 
          public virtual B_interface 
                {
    using A::isEqual;
    isEqual(shared_ptr<B_Interface> obj){
    ...
    }
};


class C : public virtual B,
          public virtual C_interface 
  {
    using B::isEqual;
    isEqual(shared_ptr<C_Interface> obj){
    ...

    bool parentIsEquals = B::isEqual(obj);

    ...
    }
};

为了避免 B 类中的名称隐藏,我明确声明了

using A::isEqual;

解决了问题的语句,但现在在类 C 中,当我想引用方法“isEqual”父类 B 并像这样明确指定它时

bool parentIsEquals = B::isEqual(obj);

我得到了错误

"B::isEqual' is ambiguous"

我也明白,因为我有两个签名,即

using A::isEqual;
isEqual(shared_ptr<B_Interface> obj);

我不知道如何解决这个问题,因为这种情况下的参数“obj”确实与购买的签名匹配。 我想了解是否有更好的模式/建议来实现这个问题。

【问题讨论】:

  • 到处都是代码异味 :) 您到底想比较什么? as 和 Bs 和 Cs 和智能指针呢?你不需要所有这些机器。
  • 如果我有一个std::unique_ptr&lt;B&gt; 并想将它与A 进行比较怎么办?如果我有一个原始指针怎么办?还是参考?为什么你的平等接口关心它的用户如何管理对象生命周期?

标签: c++


【解决方案1】:

保持简单。

具有以下类层次结构:

struct A     { int value1; };
struct B : A { int value2; };
struct C : B { int value3; };

您可以为As、Bs 和Cs 定义相等运算符

bool operator==(A const& lhs, A const& rhs)
{
    return lhs.value1 == rhs->value1;
}
bool operator==(B const& lhs, B const& rhs)
{
    return lhs.value2 == rhs->value2
           && static_cast<A const&>(lhs) == static_cast<A const&>(rhs);
}
bool operator==(C const& lhs, C const& rhs)
{
    return lhs.value3 == rhs->value3
           && static_cast<B const&>(lhs) == static_cast<B const&>(rhs);
}

有了它,加了点糖:

template<class Wrapper>
bool operator==(A const& lhs, Wrapper const& rhs)
{ return lhs == *rhs; }
template<class Wrapper>
bool operator==(Wrapper const& rhs, A const& lhs)
{ return rhs == lhs; }
// and so on...

所有这些简单的功能都为您提供了极大的灵活性:

B b1{{1}, 2};
auto c2 = std::make_unique<C>(C{{{1}, 2}, 3});
bool const equals = b1 == c2; // true

【讨论】:

  • 你能解释一下第二个模板的含义,即“template bool operator==(Wrapper const& rhs, A const& lhs) { return rhs == lhs; }” 为什么我们需要这个?
  • c++ 中是否有办法强制所有继承自 A 的类实现 operator== ?即 make 是某种纯虚拟运算符?
  • @Tito 第二个是第一个的镜像,允许a == bb == a。是的,您可以拥有纯虚拟运算符,但需要在每个子类中重写它,只提供免费功能。不要把事情复杂化:最好有一个编译时特定的错误,而不是一些纯虚函数调用的运行时崩溃。
猜你喜欢
  • 1970-01-01
  • 2015-03-20
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多