Virtual operator== overloading in derived templat classes

May 5, 2010 at 10:30pm
Hi,
I'm fairly new to C++ (old Ada guy), and I'm having a problem which I hope you experts can help me resolve. I am implementing a callback functionality. Here are my template classes:

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
43
44
45
46
47
48
49
50
51
52
53
template <class CallbackParameter>
class CallbackBase
{
public:
    virtual void operator()(CallbackParameter) const = 0;
    virtual CallbackBase<CallbackParameter>* clone() const = 0;
    virtual bool operator==(const CallbackBase<CallbackParameter> &other) const 
    {
        cout << "Inside CallbackBase operator==()\n";
        return false;
    }
//    virtual bool operator!=(const CallbackBase &other) const = 0;
};



template <class CallbackParameter, class ClientClass>
class Callback : public CallbackBase<CallbackParameter>
{
public:
    typedef void (ClientClass::*MemberFunctionPointer)(CallbackParameter);

    Callback(ClientClass& clientArg, MemberFunctionPointer memberFunctionArg)
    : theClient(clientArg), memberFunctionPtr(memberFunctionArg)
    {
    }

    void operator()(CallbackParameter callbackParam) const
    {
        (theClient.*memberFunctionPtr)(callbackParam);
    }

    Callback<CallbackParameter, ClientClass>* clone() const
    {
        return new Callback<CallbackParameter, ClientClass> (*this);
    }

    bool operator==(const Callback<CallbackParameter, ClientClass> &other) const
    {
        cout << "Inside Callback operator==()\n";

        return (theClient == other.theClient) && ( *(memberFunctionPtr) == *(other.memberFunctionPtr) );
    }

    bool operator!=(const Callback<CallbackParameter, ClientClass> &other) const
    {
        return !(*this == other);
    }

private:
    ClientClass& theClient;
    MemberFunctionPointer memberFunctionPtr;
};


I create a Callback object with:
 
Callback<CollectionElementCallbackParameter*, OwcScanController>* m_ResourceManagerCallback = new Callback<CollectionElementCallbackParameter*, OwcScanController>( *this, &OwcScanController::handleResourceManagerCallbacks );


Then I call a function to maintain a list of pointers to "registered" callbacks that I use to dispatch the callback when some event occurs using this code:
1
2
3
4
5
6
7
8
9
10
11
// In the ResourceManager.hpp class header file
static list<CallbackBase<CollectionElementCallbackParameter*>*> m_CallbackList;

// In the ResourceManager.cpp class implementation file
void ResourceManager::AddClasswideCallback(CallbackBase<CollectionElementCallbackParameter*>& theCallback)
{
    CallbackBase<CollectionElementCallbackParameter*>* theCallbackCopy = theCallback.clone();

    bool test = (*theCallbackCopy == theCallback);
    m_CallbackList.push_back(theCallbackCopy);
}


The problem is that the == operator always executes the virtual operator== function in the CallbackBase class, and not then one in my derived Callback class as I need it to do. I actually need the derived == function in the ResourceManager::RemoveClasswideCallback(CallbackBase<CollectionElementCallbackParameter*>& theCallback) function, but I didn't want to muddy the waters even more.

Thanks Much for any help, I've spent hours searching the Web and can't find a single example of operator== overloading in derived template classes.
May 5, 2010 at 11:23pm
It can be done, but it is ugly. The problem is that the derived class' operator== does not have the same signature
as the base class' operator==, and therefore is not an override.

Do you need to be able to compare callbacks? I'm not sure line 42 is going to do what you want it to do
anyway. I think you want to check if theClient refers to the same object as other.theClient, but that is not what
the code checks.

If you don't need the comparison, then you can simplify the code a lot by using boost::function and boost::bind
instead (assuming you have access to the boost libraries) because they provide you with the same functionality
and a lot more.

May 5, 2010 at 11:52pm
I realized that the derived class' operator== does not have the same signature as the base class' operator==, but since it is a derived from the base, and the == operator needs to take an object of its own class type, I thought the compiler would know that it overrides the virtual BaseClass == operator. I don't have access to boost (not allowed to use Open Source code), and I already have a large code base using this implementation, but I'm debugging the RemoveClasswideCallback() function, and my comparison (like the bool test line 9) doesn't work since it can't get into line 42 of the derived class code using objects of the base class type (CallbackBase).

I think line 42 is correct, it checks that they are of the same class, and pointing to the same member function. At least that was my intention ;-)

Is it not possible for a derived class to override the base class == operator, and make use of its own member data in the comparison function? Like it the standard examples where base class is a Shape and the derived class is a Circle, is there a way to have the Circle operator==(const Circle& myShape) override Shape::==(const Shape& myShape) so you can compare two objects of type Shape, be they Circles (comparison uses radius member data), or Rectangles (comparison uses width and height member data) and have the correct behavior?

Thanks,
Steve
May 6, 2010 at 2:42am
Line 42 does a member-wise comparison of the elements of the class. So for example:

1
2
ClientClass inst1;
ClientClass inst2( inst1 );


By your code, inst1 and inst2 would compare equal even though they are different instances.
Is that what you intend?

There was a solution to this problem posted here a while back. You might try searching for it.
May 6, 2010 at 2:52am
May 6, 2010 at 8:26am
I prefer this solution over the one in the link:

1
2
3
4
5
6
7
8
9
10
11
12
template <class CallbackParameter, class ClientClass>
class Callback : public CallbackBase<CallbackParameter>
{
public:
...
    bool operator==(const CallbackBase<CallbackParameter> &other) const
    {
        if( Callback<CallbackParameter, ClientClass>* ptr = dynamic_case<Callback<CallbackParameter, ClientClass>*>(&other) )
            return (theClient == ptr->theClient) && ( *(memberFunctionPtr) == *(ptr->memberFunctionPtr) );
        return false;
    }
...



Ciao, Imi.

PS:
I'm fairly new to C++ (old Ada guy)

Ada? I thought they died out millions of years ago when the meteor struck the ea... oh, wait. That was Cobol. :-P (sry, couldn't resist :D)
Last edited on May 6, 2010 at 8:28am
Topic archived. No new replies allowed.