Otto V.
Otto V.

Reputation: 179

How can i get a pointer to the method calling (Q)Object?

I need the pointer to the specific object, that calls the method I'm in to compare the calling objects type to a specific type.

Here I cannot do it by using parent() and i cannot use sender() because the method is not called via signal/slot. Also it would take too much effort to pass the pointer as an argument because the "target" method is used by many classes and sometimes it's even used as a slot.

I need this for a big existing code so it's not a viable option to change the software structure. Sadly i have to deal with the software as it is.

void ClassA::callingFunction()
{
    AnyObject *obj = new AnyObject();
    obj->desiredMethod();
}

void ClassB::callingFunction()
{
    AnyObject *obj = new AnyObject();
    obj->desiredMethod();
}

void AnyObject::desiredMethod()
{
    QObject *callingObject = ?
    //Here i need a pointer to the instance of ClassA/ClassB which calls this method

    bool bTypeMatch = typeid(*callingObject) == typeid(ClassA);
    if(bTypeMatch) {...}
}

Upvotes: 0

Views: 549

Answers (4)

This would be perhaps the only time where you have truly no choice but to call on the preprocessor to help you out. The desiredMethod is defined to be a fully qualified name, so that if the same method name is used elsewhere, it shouldn't compile and you'll be aware of the problem rather than facing possibly silent corruption of unrelated code.

Since desiredMethod is called with an argument of correct type, there's no reason to do any manual type casting. Instead, overload on the types you want to handle. If you want a default handler, you can implement desiredMethod(QObject * o): it'll catch all calls not handled by more specific overloads, since QObject is a base class of all the derived types you intend to handle.

#include <QtCore>

struct ClassA;
struct ClassB;

static enum { NONE, A, B } from = NONE;
struct AnyObject {
   void desiredMethod(ClassA *) { from = A; }
   void desiredMethod(ClassB *) { from = B; }
};

#define desiredMethod() ::AnyObject::desiredMethod(this)

struct ClassA : public QObject {
   void callingFunction() { AnyObject().desiredMethod(); }
};

struct ClassB : public QObject {
   void callingFunction() { AnyObject().desiredMethod(); }
};

int main() {
   ClassA a;
   ClassB b;
   Q_ASSERT(from == NONE);
   a.callingFunction();
   Q_ASSERT(from == A);
   b.callingFunction();
   Q_ASSERT(from == B);
}

Upvotes: 0

Marek R
Marek R

Reputation: 37927

from question:

Also it would take too much effort to pass the pointer as an argument because the "target" method is used by many classes and sometimes it's even used as a slot.

So add default value for argument or provide overloaded version so you could update code only in needed places.

So improving answer from @TheDarkKnight IMO this could look like this:

void AnyObject::desiredMethod()
{
    desiredMethod(NULL);  //nullptr in C++ 11
}

void AnyObject::desiredMethod(ClassA* callingClassPtr) // not casting is not needed
{    
    if(callingClassPtr)
    {
         // extra action
    }
}

Upvotes: 0

TheDarkKnight
TheDarkKnight

Reputation: 27611

Pass in the ptr to the calling object and you can dynamic_cast to check its type

void AnyObject::desiredMethod(QObject* callingClassPtr)
{    
    ClassA* aPtr = dynamic_cast<ClassA*>(callingClassPtr);
    if(aPtr != nullptr) //nullptr in C++ 11
    {
        // I'm of type ClassA*
    }
}

Other than this, there is no other way of achieving your goal.

Upvotes: 1

Andrei R.
Andrei R.

Reputation: 2462

you can pass pointer of caller as QObject * and then either:

  1. check type name with QObject::metaObject()->className()
  2. check if object casts to required type by qobject_cast
  3. set additional class meta information width Q_CLASSINFO and check against it

Of course, to make it work you need either QObject-derived caller classes, or pointers to QObject.

Only thing i'm sure about is that you'll not be able to get pointer to caller from direct function call without sender parameters

Upvotes: 1

Related Questions