0

Background:

I have a base class, Base, which has mostly 'pure' virtual functions and some non-virtual functions (plus a couple of virtual functions).

Basically, the common functionality in all the derived classes Derived, Derived2, etc, is present in the base class as non-virtual functions.

Question: If one of the objects from any of the derived classes, calls any of the non-virtual functions from the Base class, how (if at all) could it be possible to know which derived-class-object has called this non-virtual base-class function.

Actually, I wanted to debug one call and stumbled upon the fact that, neither with the debugger nor with any tracelines, can I ascertain from which derived-class-object did I stumble into this non-virtual base-class-function.

Come to think of it, as I was writing this question, one way, I can think is, I could have a static member string variable in each derived class and pass that as an argument to the non-virtual base class functions. But, is that the only way?

Minimum Working Example: Here is the minimum working example. I stripped it down as far as possible.

#include <iostream>


#include <pthread.h>
#include <string>
#include <errno.h>
#include <cstring>

class Base {
public:
    Base() {}
    virtual ~Base() {}
    int waitForThreadToExit() {
        int error = pthread_join(m_Thread, NULL);
        if (0 != error) {
            std::cerr << "Error from pthread_join(). errorCode:" << strerror(errno) << std::endl;
        }
        return error;
    }

    int start() {
        if ((startThread()) != 0) {
             std::cerr << "error returned from the start() function." << std::endl;
         }
    }

protected:
    virtual int runThread(void) {
      std::cout << "Reimplement" << std::endl;;
      return -1;
    }
    int startThread() {
        int error = pthread_create(&m_Thread, NULL, internalThreadEntryFunc, this);
        return error;
    }

private:
    static void* internalThreadEntryFunc(void* This) {
        ((Base *) This)->runThread();
        return NULL;
    }
    pthread_t m_Thread;
};


class Derived: public Base {
public:
    Derived() {}
    virtual ~Derived() {}

private:
    virtual int runThread(void) {
        while(1) {
             std::cout << "Sehr gut!" << std::endl;;
             return 0;
        }
    }

};

class Derived2: public Base {
public:
    Derived2() {}
    virtual ~Derived2() {}

private:
    virtual int runThread(void) {
        while (1)
        {
            std::cout << "Sehr sehr gut!" << std::endl;;
            return 0;
        }
    }

};


int main()
{
    std::cout << "Hello World!" << std::endl;
    Derived d;
    Derived2 d2;
    d.start();
    d2.start();
    d.waitForThreadToExit();
    d2.waitForThreadToExit();
    return 0;
}
Duck Dodgers
  • 3,409
  • 8
  • 29
  • 43
  • 2
    Printing this would tell you the type. With Visual Studio, it's obvious the type of the object, and same for gdb. – Matthieu Brucher Dec 18 '18 at 14:10
  • @MatthieuBrucher, :O fast! indeed! I did not think of that! – Duck Dodgers Dec 18 '18 at 14:13
  • 1
    You should probably join in `~Base()` if you haven't already when it comes there. If you have C++11 or later, it might also be worth taking a look at the standard `` library. It's very similar to pthread but has nicer (C++) locks/mutexes etc. – Ted Lyngmo Dec 18 '18 at 14:29
  • And what is the advantage of joining in the Base class destructor? (p.s. I don't have C++11.) – Duck Dodgers Dec 18 '18 at 14:46
  • @MatthieuBrucher, printing `this` indeed tells me the pointer address. Yes, that is a way (albeit an indirect way) to find out which one of the derived objects called the base-class function. But your comment has a 2nd part which I failed to spot earlier. I have here *gdb* and *eclipse* and I was debugging and stepping into the function. Neither the _stack_ gives me such information nor do I see anywhere here the _object type_. Googling, I found this [link](https://stackoverflow.com/questions/9568201/gdb-show-typeinfo-of-some-data/30921053) Are you referring to this `ptype` command in *gdb*? – Duck Dodgers Dec 18 '18 at 15:30
  • 2
    If the base class has virtual function then `typeid(*this)` will provide the type_info object of the most derived type. So in gdb you can get the name of the most derivied type with `printf "%s\n",typeid(*this).__name` or just `pring typeid(*this)` – Oliv Dec 18 '18 at 16:27
  • @Oliv, maybe it is an effect of my ancient compiler, but I can't access `__name`. BUT, I can use `name()` member-function. So this works for me, `typeid(*this).name()`. – Duck Dodgers Dec 20 '18 at 13:51
  • @joeyMallone The opposite for me, I can't call member functions. And I would appreciate it. Which debugger/compiler do you use? I use gcc/gdb v8.2. – Oliv Dec 20 '18 at 16:27
  • @Oliv, I am forced to use _gcc 4.4.5_ with _gdb 7.0.1_ . Maybe it is noteworthy (or not), but I have _glibc 2.11.3_ – Duck Dodgers Dec 21 '18 at 08:46

1 Answers1

0

So just to be complete, in case someone else (quite possibly me myself in a few months time) stumbles upon this question again, here is the general idea that I implemented for this problem.

#include <iostream>
#include <typeinfo>

class base {
public:
    virtual const char* name() {
        return typeid(*this).name();
    }
    virtual ~base(){}
};

class derived : public base {};
class otherDerived : public base {};

int main () {
    base b;
    derived d;
    otherDerived d2;

    std::cout << "base says:" << b.name() << std::endl;
    std::cout << "derived says:" << d.name() << std::endl;
    std::cout << "other derived says:" << d2.name() << std::endl;
}

which gives the output when run in my QtCreator:

base says:4base
derived says:7dervied
other derived says:12otherDerived

Note: Best to make a virtual function name() or className() and call that functio n everywhere, instead of sprinkling typeid(*this).name() everywhere in the code.

Duck Dodgers
  • 3,409
  • 8
  • 29
  • 43