How to force a derived class comparison

Jun 18, 2012 at 5:10am
Hello,
I have a virtual class Element that forces its derived classes to have a == operator:

class Element {
virtual int operator==(Element *)=0;
}

So, I have derived classes (Integer, Word) that implement that operator.

I have a class Group that basically is a list of elements.

In a function, I want to compare if an element from a group its equal to an element of a different group, so I'm using:

if(actual == lookingfor)

where both actual and lookingfor are pointers to Element...but the comparison is being made at the level of pointers, so both pointers are always different.

How can I force that the operator == from the derived class of element be used?


Last edited on Jun 18, 2012 at 5:19am
Jun 18, 2012 at 5:30am
You need to compare references, not pointers.

Something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <typeinfo>
#include <exception>

struct element
{
    virtual bool operator== ( const element& that ) const = 0 ;
    // ...
};

struct integer : element
{
    virtual bool operator== ( const element& that ) const override
    {
        try { return value == dynamic_cast< const integer& >(that).value ; }
        catch( const std::bad_cast& ) { return false ; }
    }

    int value ;

    // ...
};

struct word : element
{
    virtual bool operator== ( const element& that ) const override
    {
        try { return str == dynamic_cast< const word& >(that).str ; }
        catch( const std::bad_cast& ) { return false ; }
    }

    std::string str ;

    // ...
};

inline bool equal_objects( const element* actual, const element* looking_for )
{ return actual && looking_for && ( *actual == *looking_for ) ; }

inline bool same_object( const element* actual, const element* looking_for )
{ return actual == looking_for ; }

Jun 18, 2012 at 5:45am
Thanks JL, the thing is that the base function for comparison uses pointer to element, I have to stick to this declaration:

class Element {
virtual int operator==(Element *)=0;
}

So I wrote:

class Word : public Element {
private:
char * ptr;
public:
int operator==(Element *);
}

int Word::operator==(Element * element){
Element * ptr = element;
Word * wordPtr = dynamic_cast< Word * >(ptr);
int equal = 0;
if(wordPtr){
equal = strncmp(this->ptr,wordPtr->ptr,49)==0;
}
return equal;
}

And in the Group class that it's basically a list, this method has to work with any class derived from Element:

Group::Iterator Group::look(Element * lookingPtr){
Iterator iterador(this->begin());
Iterator fin = this->end();
Element * elActual = *iterator;

while((elActual != elBuscadoPtr) && (iterador != fin)){
++iterador;
elActual = *iterador;
}
return iterador;
}
Jun 18, 2012 at 6:19am
> the base function for comparison uses pointer to element,
> I have to stick to this declaration:

Hmm.. that looks counter-intuitive to me; if it is your own base class, consider modifying it. And while you are at it, also make the code const-correct.

If not, something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
struct element
{
    virtual bool operator== ( const element* that ) const = 0 ;
    // ...
};

struct integer : element
{
    virtual bool operator== ( const element* that ) const override
    {
        const integer* that_integer = dynamic_cast< const integer* >(that) ;
        return that_integer && value == that_integer->value ;
    }

    int value ;

    // ...
};

struct word : element
{
    enum { SIZE = 50 } ;

    virtual bool operator== ( const element* that ) const override
    {
        const word* that_word = dynamic_cast< const word* >(that) ;
        return that_word && !std::strncmp( cstr, that_word->cstr, SIZE ) ;
    }

    char cstr[SIZE] ;

    // ...
};

inline bool equal_objects( const element* actual, const element* looking_for )
{
    return actual && ( *actual == looking_for ) ;
    // or equivalently: return actual && actual->operator== ( looking_for ) ;
}

inline bool same_object( const element* actual, const element* looking_for )
{ return actual == looking_for ; }


And then:
1
2
3
4
5
6
7
8
9
10
11
12
13
group::const_iterator group::look( const element* elBuscadoPtr ) const
{
    for( auto iterator = begin() ; iterator != end(), ++iterator )
        if( equal_objects( *iterator, elBuscadoPtr ) ) return iterator ;
    return end ;
}

group::iterator group::look( const element* elBuscadoPtr )
{
    for( auto iterator = begin() ; iterator != end(), ++iterator )
        if( equal_objects( *iterator, elBuscadoPtr ) ) return iterator ;
    return end ;
}

Topic archived. No new replies allowed.