Address of virtual member function from object (*not* class)

  • Thread starter Gabriel de Dietrich
  • Start date
G

Gabriel de Dietrich

Hi all!

Just out of curiosity: Is there any way to get the address of a
particular virtual member function given an object? Some code to make
things more clear...

class A
{
public:
A() { }
virtual void f() { }
};

class B: public A
{
public:
B() { }
virtual void f() { }
};

typedef void (A::*FPtr)();

FPtr getFAddress(A* obj)
{
return &obj->f; // FIXME This won't compile (at least on VC++ 8)
}

int main()
{
A a;
B b;

getFAddress(&a); // Should return &A::f
getFAddress(&b); // Should return &B::f
}


The "intuituve" solution of this implementation of getFAddress
doesn't even compile on VC++ 8 (error C2276 if that matters). Note
that f is virtual, so the address depends on the object's class. Now,
if the compiler can generate the code to get the address of the right
f member, why can't we use this for our own code? (OK, this may lead
to lots of catastrophic code -- like the end of polymorphism as we
know it, but anyway...). I don't really think there is a portable
solution for this, but if someone has had this problem before, I'm
curious to see their solution.

Thanks,

Gabriel
 
C

cch@srdgame

于 Tue, 02 Sep 2008 05:22:50 -0700,Gabriel de Dietrich写到:
Hi all!

Just out of curiosity: Is there any way to get the address of a
particular virtual member function given an object? Some code to make
things more clear...

class A
{
public:
A() { }
virtual void f() { }
};

class B: public A
{
public:
B() { }
virtual void f() { }
};

typedef void (A::*FPtr)();

FPtr getFAddress(A* obj)
{
return &obj->f; // FIXME This won't compile (at least on VC++ 8)
}

int main()
{
A a;
B b;

getFAddress(&a); // Should return &A::f getFAddress (&b); // Should
return &B::f
}


The "intuituve" solution of this implementation of getFAddress
doesn't even compile on VC++ 8 (error C2276 if that matters). Note that
f is virtual, so the address depends on the object's class. Now, if the
compiler can generate the code to get the address of the right f member,
why can't we use this for our own code? (OK, this may lead to lots of
catastrophic code -- like the end of polymorphism as we know it, but
anyway...). I don't really think there is a portable solution for this,
but if someone has had this problem before, I'm curious to see their
solution.

Thanks,

Gabriel

Is follow title suitable for you?

http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx
 
G

Gabriel de Dietrich

"Curiosity" is not really a valid reason, I believe.  So, really, why
would you want to do that?  You're not using the pointer-to-member in
any way, so what would be the point of returning it?

Well, it is for me... :)

To answer your question: Suppose you have an arbitrarily large
inheritance hierarchy with root class A, and you want to know if some
subclass reimplements f. If you know the class, no problem. Just test

&A::f == &B::f

or whatever other class, and it's done. Now, suppose you don't know
the class because all you have is a polymorphic pointer to an object
(like in "A* obj"). In this case you would test

&A::f == getFAddress(obj)

With my example code, this would be true if the class of *obj is A,
and false if it's B. Moreover, you don't know all the classes from the
inheritance hierarchy, so you can't (or don't want to) check your
object against all the classes using typeid, or dynamic_cast, or
whatever.

As for the final purpose of this, I don't have any. If you want to
know, it's just an idea I had when trying to deal with exceptions in
event handlers using the wxWidgets framework. But I've found a better
solution, at least more -- let's say -- natural.
 
F

Fei Liu

Gabriel said:
Well, it is for me... :)

To answer your question: Suppose you have an arbitrarily large
inheritance hierarchy with root class A, and you want to know if some
subclass reimplements f. If you know the class, no problem. Just test

&A::f == &B::f

or whatever other class, and it's done. Now, suppose you don't know
the class because all you have is a polymorphic pointer to an object
(like in "A* obj"). In this case you would test

&A::f == getFAddress(obj)

With my example code, this would be true if the class of *obj is A,
and false if it's B. Moreover, you don't know all the classes from the
inheritance hierarchy, so you can't (or don't want to) check your
object against all the classes using typeid, or dynamic_cast, or
whatever.

As for the final purpose of this, I don't have any. If you want to
know, it's just an idea I had when trying to deal with exceptions in
event handlers using the wxWidgets framework. But I've found a better
solution, at least more -- let's say -- natural.
You can use metaprogramming technique to query if a class implements f.

Fei
 
J

James Kanze

Well, it is for me... :)
To answer your question: Suppose you have an arbitrarily large
inheritance hierarchy with root class A, and you want to know
if some subclass reimplements f. If you know the class, no
problem. Just test
&A::f == &B::f
or whatever other class, and it's done.

If I read the standard correctly, that test shoud always return
true (supposing that f is virtual, and that B derives from A).
Regardless of whether B overrides the function or not. (I'm not
100% sure about my reading of the standard here, however, since
both of the compilers available to me say that the comparison is
illegal.)

Pointers to members respect virtuality; a pointer to a virtual
function will "point" to the correct function in whatever object
it happens to be used with.
 
J

James Kanze

Fei Liu wrote:

[...]
Well, yes, but the point is that metaprogramming will only check with
the static type of the pointer, not with its dynamic. So, no go with
templates in this case...

Actually, you can't use metaprogramming to query what the
original poster wanted, even on statically known types.
Metaprogramming can query whether a class has a function f, but
it can't distinguish whether that function is present because the
class implemented it directly, or because it inherited it from a
base class.
 
J

James Kanze

Yes, but, again, how would he get a pointer to member from a
pointer to an object (possibly of the derived type)?

You can't. Generally speaking, pointer to member is a static
concept (since pointers to members exist in the absense of any
actual object).
Would 'typeid' help?

Not the standard typeid, anyway. An implementation could extend
it so that it did (say by adding a function to std::type_info
which returned a reference to a _Class---an implementation
defined class along the lines of Java's java.lang.Class), but I
don't know of any which do. (As far as I know, the demand for
it is quite low. When I used Java, except for a few limited
uses which are easily implemented differently---and more
safely---in C++, the only use I found for it was for some
generic test programs of data containers.)
 
G

Gabriel de Dietrich

So, it seems that Old Bjarne didn't want any of us to inspect the
innards of classes and objects. (Like class meta-programming in, e.g.,
Python). That leaves us with hacking around the vtable as the only
solution. Well, I'm a bit less curious about that... (OK, I did
inspect the assembly code generated by VC++, only to learn that it was
less than obvious how to guess the entry number in the vtable for a
given method).

Thank you all for the replies. I've learned a couple of interesting
things.

Gabriel
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top