Æle*_*lex 3 c++ polymorphism inheritance equality
我想把自己的头缠在我已经想了很长时间的事情上。假设我有一堂课Base
class Base
{
public:
    virtual ~Base(){}
    virtual bool operator== ( const Base & rhs ) const;
};
现在,另一个类继承自它。它有两个相等运算符:
class A : public Base
{
public:
    bool operator== ( const A & rhs ) const;
    bool operator== ( const Base & rhs ) const;
private:
    int index__;
};
还有另一个也继承自Base的类,它还具有两个相等运算符:
class B : public Base
{
public:
    bool operator== ( const B & rhs ) const;
    bool operator== ( const Base & rhs ) const;
private:
    int index__;
};
这是我的理解(不一定正确)。我只能使用第一个运算符来检查相同的类对象是否相等。但是,我可以使用第二个运算符来检查它们是否是相同类型的类,然后是否相等。现在,存在另一个类,该类环绕Base的指针,但是这些指针是多态类型A或B。
class Z
{
public:
    bool operator== ( const Z & rhs ) const;
private:
    std::shared_ptr<Base> ptr__;
};
首先,我发现我不能让两个operator ==重载。我没有从编译器中得到任何错误,但是当我尝试运行它时,它只是挂起了。我猜想它与rtti有关,这超出了我的范围。
我一直在使用并且非常难看的是尝试向下转换,如果可以,然后尝试在类Z中比较实例:
bool Z::operator== ( const Z & rhs ) const
{
    if ( const auto a1 = std::dynamic_pointer_cast<A>( this->ptr__ ) )
        if ( const auto a2 = std::dynamic_pointer_cast<A>( rhs.ptr__ ) )
            return *a1 == *a2; 
    else if ( const auto b1 = std::dynamic_pointer_cast<B>( this->ptr__ ) )
        if ( const auto b2 = std::dynamic_pointer_cast<B>( rhs.ptr__ ) )
            return *b1 == *b2;
    return false;
}
这非常丑陋,并且假设您的类A和B具有相等运算符,该运算符将相同类型的类作为参数。
因此,我尝试提出一种方法,该方法将使用第二种类型的运算符,如果可以的话,它更不可知,更优雅。并失败了。这将要求在A类和B类中都使用它,从而将其从Z类中移开。
bool A::operator== ( const Base & rhs ) const
{
    return ( typeid( *this ) == typeid( rhs ) ) && ( *this == rhs );
}
与B类相同。这似乎不起作用(应用程序挂起,没有任何错误)。此外,它使用某种默认运算符,还是使用基类运算符?理想情况下,它应同时使用Base :: operator ==并比较类类型。
但是,如果我想根据类A或B的成员进行更详尽的比较,例如,index__那么我显然必须与每个类做朋友,因为当我尝试这样做时,它将无法编译(除非我添加一个吸气或使其以某种方式可见):
bool A::operator== ( const Base & rhs ) const
{
    return ( typeid( *this ) == typeid( rhs ) )
           && (*this == *rhs )
           && (this->index__ == rhs.index__ );
}
是否有一个优雅,简单的解决方案?我是否只限于垂头丧气和尝试,还是有其他方法可以实现我想要的目标?
我同意@vsoftco关于仅operator==在基类中实现并使用NVI习惯用法的观点。但是,我将提供派生类需要实现以执行相等性检查的纯虚函数。这样,基类就不知道或不在乎任何派生类等效是什么意思。
#include <iostream>
#include <string>
#include <typeinfo>
class Base
{
public:
    virtual ~Base() {}
    bool operator==(const Base& other) const
    {
        // If the derived types are the same then compare them
        return typeid(*this) == typeid(other) && isEqual(other);
    }
private:
    // A pure virtual function derived classes must implement.
    // Furthermore, this function has a precondition that it will only
    // be called when the 'other' is the same type as the instance
    // invoking the function.
    virtual bool isEqual(const Base& other) const = 0;
};
class D1 : public Base
{
public:
    explicit D1(double v = 0.0) : mValue(v) {}
    virtual ~D1() override {}
private:
    virtual bool isEqual(const Base& other) const
    {
        // The cast is safe because of the precondition documented in the
        // base class
        return mValue == static_cast<const D1&>(other).mValue;
    }
private:
    double mValue;
};
class D2 : public Base
{
public:
    explicit D2(std::string v = "") : mValue(v) {}
    virtual ~D2() override {}
private:
    virtual bool isEqual(const Base& other) const
    {
        return mValue == static_cast<const D2&>(other).mValue;
    }
private:
    std::string mValue;
};
class D3 : public Base
{
public:
    explicit D3(int v = 0) : mValue(v) {}
    virtual ~D3() override {}
private:
    virtual bool isEqual(const Base& other) const
    {
        return mValue == static_cast<const D3&>(other).mValue;
    }
private:
    int mValue;
};
int main()
{
    D1 d1a(1.0);
    D1 d1b(2.0);
    D1 d1c(1.0);
    D2 d2a("1");
    D2 d2b("2");
    D2 d2c("1");
    D3 d3a(1);
    D3 d3b(2);
    D3 d3c(1);
    std::cout << "Compare D1 types\n";
    std::cout << std::boolalpha << (d1a == d1b) << "\n";
    std::cout << std::boolalpha << (d1b == d1c) << "\n";
    std::cout << std::boolalpha << (d1a == d1c) << "\n";
    std::cout << "Compare D2 types\n";
    std::cout << std::boolalpha << (d2a == d2b) << "\n";
    std::cout << std::boolalpha << (d2b == d2c) << "\n";
    std::cout << std::boolalpha << (d2a == d2c) << "\n";
    std::cout << "Compare D3 types\n";
    std::cout << std::boolalpha << (d3a == d3b) << "\n";
    std::cout << std::boolalpha << (d3b == d3c) << "\n";
    std::cout << std::boolalpha << (d3a == d3c) << "\n";
    std::cout << "Compare mixed derived types\n";
    std::cout << std::boolalpha << (d1a == d2a) << "\n";
    std::cout << std::boolalpha << (d2a == d3a) << "\n";
    std::cout << std::boolalpha << (d1a == d3a) << "\n";
    std::cout << std::boolalpha << (d1b == d2b) << "\n";
    std::cout << std::boolalpha << (d2b == d3b) << "\n";
    std::cout << std::boolalpha << (d1b == d3b) << "\n";
    std::cout << std::boolalpha << (d1c == d2c) << "\n";
    std::cout << std::boolalpha << (d2c == d3c) << "\n";
    std::cout << std::boolalpha << (d1c == d3c) << "\n";
    return 0;
}
Compare D1 types
false
false
true
Compare D2 types
false
false
true
Compare D3 types
false
false
true
Compare mixed derived types
false
false
false
false
false
false
false
false
false
| 归档时间: | 
 | 
| 查看次数: | 916 次 | 
| 最近记录: |