What is the correct way to implement comparison for a base class?

I have a base class

class Animal 

with pure virtual functions and a set of derived classes

 class Monkey : public Animal class Snake : public Animal 

I want to implement a comparison operation so that if I encounter two pointers to Animals in my code

 Animal* animal1 Animal* animal2 

I can compare them with each other. Comparison should give false values ​​if animal1 and animal2 have different derived classes. If they have the same derived class, the output of the comparison operator must be returned.

Can someone point me to a good way to implement this?

+6
c ++ inheritance
source share
5 answers

Wow, many other answers were so completely unnecessary. dynamic_cast - it exists, use it.

 class Animal { public: virtual bool operator==(const Animal& other) = 0; virtual ~Animal() = 0; }; template<class T> class AnimalComp : public Animal { public: virtual bool operator==(const Animal& ref) const { if (const T* self = dynamic_cast<const T*>(&ref)) { return ((T*)this)->operator==(*self); } return false; } virtual bool operator!=(const Animal& ref) const { if (const T* self = dynamic_cast<const T*>(&ref)) { return ((T*)this)->operator!=(*self); } return true; } }; class Monkey : public AnimalComp<Monkey> { public: virtual bool operator==(const Monkey& other) const { return false; } virtual bool operator!=(const Monkey& other) const { return false; } }; class Snake : public AnimalComp<Snake> { public: virtual bool operator==(const Snake& other) const { return false; } virtual bool operator!=(const Snake& other) const { return false; } }; 

Edit: Worship my automatic template customization!

Editing editing. One thing I did was forget to mark them as const, which was not the case. I won’t apologize for what I’m not doing! = How, let him face it, realizing it - this is a complete failure.

More rights: guys from Jesus Christ, this is not an example of how to write! = Or ==, this is an example of how to use CRTP. If you do not like how I decided to implement mine! = Or ==, you can sue.

+4
source share

One way to implement this is to use dual dispatch to distinguish between "one class" and "different classes":

 class Monkey; class Snake; class Animal { public: virtual bool compare_impl(const Animal*) const { return false; } virtual bool compare_impl(const Monkey*) const { return false; } virtual bool compare_impl(const Snake*) const { return false; } virtual bool compare(const Animal* rhs) const =0; }; class Monkey : public Animal { private: /* Override the default behaviour for two Monkeys */ virtual bool compare_impl(const Monkey*) const { /* compare two Monkey */ } public: /* Let overload-resolution pick the compare_impl for Monkey and let virtual dispatch select the override in the dynamic type of rhs */ virtual bool compare(const Animal* rhs) const { return rhs->compare_impl(this); } }; class Snake : public Animal { private: /* Override the default behaviour for two Snakes */ bool compare_impl(const Snake*) const { /* compare two Snakes */ } public: /* Let overload-resolution pick the compare_impl for Monkey and let virtual dispatch select the override in the dynamic type of rhs */ virtual bool compare(const Animal* rhs) const { return rhs->compare_impl(this); } }; 
+4
source share

Since there is no static type information associated with two pointers, you will need to use RTTI . You can compare the results of type typeid operator to determine if objects are of the same type.

An alternative would be to add your own type identifier to the Animal class. Add one more virtual function and the derived classes return what uniquely identifies the type. You can use an enumeration, or perhaps a type name as a string. If you can use it, RTTI will be much better IMHO.

+3
source share

Use the type_info class. It defines an operator ==, which returns whether these two types describe the same type. Here you can find the link: http://www.cplusplus.com/reference/std/typeinfo/type_info/

+2
source share

Here is a little trick I'm using (I hope it works for you too). I add the following private method for Animal and OVERRIDE in each derived class (I know this is a bit unpleasant, but faster than RTTI)

 class Animal { protected: virtual const void* signature() const { static bool dummy; return &dummy; } ... } class Monkey : public Animal { private: virtual const void* signature() const { static bool dummy; return &dummy; } ... } 

now, to make sure that 2 pointers (a and b) of the same class only check for

a-> signature () == b-> signature ()

This is not a solution, it is a trick, but it only works with two calls to virtual methods (1 for each pointer), so it is pretty fast.

0
source share

All Articles