Problem with virtual member function pointer (how to invoke the base?!)

  • Thread starter christopher diggins
  • Start date
C

christopher diggins

Hi everyone,

I have the following code (greatly simplified to demonstrate issue) :

#include <iostream>

class CBaseFuBar {
public:
virtual void Fu() { std::cout << "base"; };
};

class CDerivedFuBar : public CBaseFuBar {
public :
virtual void Fu() { std::cout << "derived"; };
};

typedef void (CBaseFuBar::*FuFxnPtr)();

int main() {
CDerivedFuBar fubar;
FuFxnPtr fxn;
fxn = &CBaseFuBar::Fu;
(fubar.*fxn)(); // prints out "derived" not "base" like I want
std::cin.get();
return 0;
};

The problem is that given CDerivedFuBar I want to get a member function
pointer to refer to the base Fu function and not automatically get resolved
to the derived Fu function. The CBaseFuBar class can not be modified, but
the CDerivedFuBar class can be. Thanks in advance!
 
V

Victor Bazarov

christopher diggins said:
I have the following code (greatly simplified to demonstrate issue) :

#include <iostream>

class CBaseFuBar {
public:
virtual void Fu() { std::cout << "base"; };

'virtual' is key here.
};

class CDerivedFuBar : public CBaseFuBar {
public :
virtual void Fu() { std::cout << "derived"; };
};

typedef void (CBaseFuBar::*FuFxnPtr)();

int main() {
CDerivedFuBar fubar;
FuFxnPtr fxn;
fxn = &CBaseFuBar::Fu;
(fubar.*fxn)(); // prints out "derived" not "base" like I want

The function is called polymorphically. For all intents and purposes
it works as if you called

fubar.Fu()
std::cin.get();
return 0;
};
^
This semicolon is a syntax error.
The problem is that given CDerivedFuBar I want to get a member function
pointer to refer to the base Fu function and not automatically get resolved
to the derived Fu function. The CBaseFuBar class can not be modified, but
the CDerivedFuBar class can be. Thanks in advance!

Don't use a pointer to member, use direct call

fubar.CBaseFuBar::Fu();

Victor
 
C

christopher diggins

Victor Bazarov said:
'virtual' is key here.


The function is called polymorphically. For all intents and purposes
it works as if you called

fubar.Fu()

Yes I realize that.
^
This semicolon is a syntax error.

Thank you for pointing that out.
Don't use a pointer to member, use direct call

fubar.CBaseFuBar::Fu();

Victor

The code I am working with specifically requires a function pointer. Is
there a way to accomplish this with a function pointer invoked on a
CDerivedFuBar object?

Thanks for you input.
 
S

Sommer Bernhard \(SMS SW SEC 88T external\)

christopher diggins said:
Hi everyone,

I have the following code (greatly simplified to demonstrate issue) :

#include <iostream>

class CBaseFuBar {
public:
virtual void Fu() { std::cout << "base"; };
};

class CDerivedFuBar : public CBaseFuBar {
public :
virtual void Fu() { std::cout << "derived"; };
};

typedef void (CBaseFuBar::*FuFxnPtr)();

int main() {
CDerivedFuBar fubar;
FuFxnPtr fxn;
fxn = &CBaseFuBar::Fu;
at this point your expression will be solved by compiler and the compiler
will always use the address of function CBaseFuBar::Fu.
The only possible way I see is to wrap your virtual funktion in a non
virtual baseclass function. Something like this:
class CBaseFuBar {
public:
virtual void Fu() { std::cout << "base"; };
void WrapIt(){Fu();}
};
now you can use your wrapper function:
int main() {
CDerivedFuBar fubar;
FuFxnPtr fxn;
fxn = &CBaseFuBar::WrapIt();
(fubar.*fxn)(); // should work
std::cin.get();
return 0;
}

regards
Bernhard
 
V

Victor Bazarov

Sommer Bernhard (SMS SW SEC 88T external) said:
[...]
The only possible way I see is to wrap your virtual funktion in a non
virtual baseclass function. Something like this:
class CBaseFuBar {
public:
virtual void Fu() { std::cout << "base"; };
void WrapIt(){Fu();}
};

The OP specifically said that the base class could NOT be modified.

Beyond that, your solution should work.
 
V

Victor Bazarov

christopher diggins said:
Yes I realize that.


Thank you for pointing that out.


The code I am working with specifically requires a function pointer. Is
there a way to accomplish this with a function pointer invoked on a
CDerivedFuBar object?

The only thing I can think of is to drop the 'Fu' member from the derived
class. Then, for any instance, the final overrider will be <base>::Fu,
and it will be called through the pointer.

Victor
 
S

Sharad Kala

Sommer Bernhard (SMS SW SEC 88T external) said:
at this point your expression will be solved by compiler and the compiler
will always use the address of function CBaseFuBar::Fu.
The only possible way I see is to wrap your virtual funktion in a non
virtual baseclass function. Something like this:
class CBaseFuBar {
public:
virtual void Fu() { std::cout << "base"; };
void WrapIt(){Fu();}
};
now you can use your wrapper function:
int main() {
CDerivedFuBar fubar;
FuFxnPtr fxn;
fxn = &CBaseFuBar::WrapIt();
This will fail to compile. It should be fxn = &CBaseFuBar::WrapIt; // NO braces
Also this program will also print derived and not base.

-Sharad
 
C

christopher diggins

Sommer Bernhard (SMS SW SEC 88T external) said:
at this point your expression will be solved by compiler and the compiler
will always use the address of function CBaseFuBar::Fu.
The only possible way I see is to wrap your virtual funktion in a non
virtual baseclass function. Something like this:
class CBaseFuBar {
public:
virtual void Fu() { std::cout << "base"; };
void WrapIt(){Fu();}
};
now you can use your wrapper function:
int main() {
CDerivedFuBar fubar;
FuFxnPtr fxn;
fxn = &CBaseFuBar::WrapIt();
(fubar.*fxn)(); // should work
std::cin.get();
return 0;
}

regards
Bernhard

Thanks for the input. I mentioned in the original post that CBaseFuBar could
not be modified, though that can be remedied easily if we place the wrapper
in the derived class :

class CDerivedFuBar {
virtual void Fu() { std::cout << "derived"; };
void WrapFu() { CBaseFuBar::Fu(); };
};
etc.

This is a working solution but not a very practical one unfortunately. I
would have to write a new wrapper function in every derived class for every
virtual function. That would be a heck of a nasty requirement to put on
users who derive from CBaseFuBar. You can imagine the redundancy as my
project scales up. I believe though that this is in fact the best we can do
with the limitations of the current standard. I am just hoping someone
proves us wrong. `
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top