c++ - Class Polymorphism and equality operators -
i trying wrap head around i've been wondering quite time now. assume have class base
class base { public: virtual ~base(){} virtual bool operator== ( const base & rhs ) const; };
now, class inherits it. has 2 equality operators:
class : public base { public: bool operator== ( const & rhs ) const; bool operator== ( const base & rhs ) const; private: int index__; };
and yet class inherits base, , has 2 equality operators:
class b : public base { public: bool operator== ( const b & rhs ) const; bool operator== ( const base & rhs ) const; private: int index__; };
this understand (which not correct). can use first operator check if same class objects equal. yet, can use second operator check if same type of class, , if equal. now, yet class exists, wraps around pointers of base, however, polymorphic types a, or b.
class z { public: bool operator== ( const z & rhs ) const; private: std::shared_ptr<base> ptr__; };
first things first, i've found out, can't have 2 operator== overloaded. no errors compiler, when try run it, hangs. guessing has rtti, beyond me.
what have been using, , quite ugly, attempting downcast, , if can, try compare instances, within class 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; }
this quite ugly, , assumes class , b, have equality operator takes parameter same type class.
so tried come way, use second type of operator, more agnostic, more elegant if will. , failed. require use in both classes , b, moving away class z.
bool a::operator== ( const base & rhs ) const { return ( typeid( *this ) == typeid( rhs ) ) && ( *this == rhs ); }
same class b. doesn't seem work (app hangs without errors). furthermore, uses kind of default operator, or use base class operator? ideally, should use both base::operator== , compare class types.
if however, want more elaborate comparison, based upon member of class a, or b, such index__
have friend each class, because when try this, won't compile (unless of course add getter or make somehow visible):
bool a::operator== ( const base & rhs ) const { return ( typeid( *this ) == typeid( rhs ) ) && (*this == *rhs ) && (this->index__ == rhs.index__ ); }
is there elegant, simple solution this? confined downcasting , trying, or there other way achieve want?
i agree @vsoftco implementing operator==
in base class , using nvi idiom. however, i'd provide pure virtual function derived classes need implement perform equality check. in way base class doesn't know or care means derived classes equivalent.
code
#include <iostream> #include <string> #include <typeinfo> class base { public: virtual ~base() {} bool operator==(const base& other) const { // if derived types same compare them return typeid(*this) == typeid(other) && isequal(other); } private: // pure virtual function derived classes must implement. // furthermore, function has precondition // called when 'other' same type instance // invoking 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 { // cast safe because of precondition documented in // 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; }
output
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
Comments
Post a Comment