0

Why can't you get a pointer to an overriden method in a derived class?

Here's an example:

Base Class

#ifndef BASE_H
#define BASE_H

class Base 
{

    typedef void (Base::*BasePointer)( void );

public:
    Base(){}

protected:

    virtual void FunFunction( void )
    {

    }

    BasePointer pointer;
};  

#endif  /* BASE_H */

Derived Class

#ifndef DERIVED_H
#define DERIVED_H

#include "Base.h"

class Derived : public Base
{
public:
    Derived()
    {
        pointer = &Base::FunFunction;

    }

protected:
    // Overrides base function
    void FunFunction( void )
    {

    }
};

#endif  /* DERIVED_H */

The constructor in the Derived class attempts to set inherited pointer value equal to the address of the overriden method FunFunction. But the error that is generated is "error: 'FunFunction' is a protected member of 'Base'". Changing FunFunction's access to public fixes this problem. FunFucntion can't be public however.

  1. Why does it have a problem with FunFunction being protected?

  2. What is a way to get this desired functionality of this isn't possible?

EDIT Could a solution involve casting this to the Base class and then taking the address of the function? Something like &(((Base*)this)::FunFunction); although that example doesn't work.

j76goatboy
  • 405
  • 2
  • 7
  • 16

2 Answers2

0

You can access to Base protected members only through Derived.

At least in VS2012 calling &Derived::Base::FunFunction from Derived yilds no error. So following code will work:

class Base 
{
public:
    typedef void (Base::*BasePointer)( void );


    Base()
    {
        pointer2 = &Base::FunFunction;
    }

protected:

    virtual void FunFunction( void )
    {
        std::cout << "Base::FunFunction\n";
    }

    BasePointer pointer;
    BasePointer pointer2;
};  

class Derived : public Base
{
public:
    Derived()
    {
        pointer = &Derived::Base::FunFunction;
    }

    void RunBaseHiddenMethod()
    {       
        (this->*(pointer))();
    }

    void RunFunFunction()
    {
        FunFunction();
    }
protected:
    // Overrides base function
    virtual void FunFunction( void ) override
    {
        std::cout << "Derived::FunFunction\n";
    }
};

int main (int argc, char *argv[]) 
{
    Derived d;
    d.RunBaseHiddenMethod();
    d.RunFunFunction();
    return 0;
}

Result:

Derived::FunFunction
Derived::FunFunction

Edit: But (as you can see) it will not help you! In debugger:

(((Base)(&(d)))).pointer 0x00be14ab {ConsoleApplication1.exe![thunk]:Base::`vcall'{0,{flat}}' }'}

(((Base)(&(d)))).pointer2 0x00be14ab {ConsoleApplication1.exe![thunk]:Base::`vcall'{0,{flat}}' }'}

The pointer holds just index of virtual function - not absolute address. Therefore pointer==pointer2.

BTW you can access static protected member functions:

class Base 
{
public:
    typedef void (BasePointer)(void );
    Base(){}

protected:
    static void FunFunction( void )
    {
        std::cout << "Base::FunFunction\n";
    }

    BasePointer* pointer;
};  

class Derived : public Base
{
public:
    Derived()
    {
        pointer = &Base::FunFunction; //OK
    }

    void RunBaseMethod()
    {       
        pointer();
    }
};

Another question: why can't we get member function absolute address (like exported address)? It is obvious that compiler knows these addresses.

Community
  • 1
  • 1
Dmitriy Zapevalov
  • 1,357
  • 8
  • 13
-1

Pure C++ does not allow creating a pointer to a member function of a class unless it is a static function. Unless you are using C++ Builder, which uses Delphi's trick to create and manage function pointers, what you are trying to do is not possible. Remember a member function of a class has a hidden parameter that points to the instance of the class.

Sam

Sam
  • 2,473
  • 3
  • 18
  • 29