Class member function address.

Hello,

is there any way to get the real address of a member function after passing it as a function argument ? (I'm almost sure the problem come from me, as I am not really fluent with pointers)

Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

class TestClass
{
	public:
		TestClass(){};
		~TestClass(){};
		void func1( std::string& ){};
};

typedef void( TestClass::*TestType)( std::string& );

class Foo
{
	public:
		Foo(){};
		~Foo(){};
			
		template <class C, class T>
		void sendMemberAddress( void(C::*funPtr)(T&), C& obj ) 		// without typedef
		{
			std::cout << "From Foo1 :: Member function address: " << (void*)&funPtr << " | Class instance address: "<< (void*)&obj << std::endl;
		}
		
		void sendMemberAddress2( TestType& funPtr, TestClass& obj )	// using typedef
		{
			std::cout << "From Foo2 :: Member function address: " << (void*)&funPtr << " | Class instance address: "<< (void*)&obj << std::endl;
		}
	};

int main()
{
	Foo x;
	TestClass a;
	std::cout << "From Main1 :: Member function address: " << (void*)&TestClass::func1 << " | Class instance address: "<< (void*)&a << std::endl;

	// Without typedef
	x.sendMemberAddress( &TestClass::func1, a );
	
	// With typedef
	TestType y = &TestClass::func1;
	std::cout << "From Main2 :: Member function address: " << (void*)&y  << " (using TestType y = &TestClass::func1)" << std::endl;
	x.sendMemberAddress2( y, a );
}


This will return something like :

From Main1 :: Member function address: 0x4024d4 | Class instance address: 0x22ff0f

Without typedef
From Foo1 :: Member function address: 0x22fef4 | Class instance address: 0x22ff0f

With typedef
From Main2 :: Member function address: 0x22ff04 (using TestType y = &TestClass::func1)
From Foo2 :: Member function address: 0x22ff04 | Class instance address: 0x22ff0f


So, as you can see the member function address (set to bold and underlined) is not the same from inside the sendMemberAddress function.

And when I try using the typedef to simplify the problem, the same problem occurs with the both prints (but the address printed from inside sendMemberAddress2 and from main for the "TestType y" is the same despite theyr are not equal to the original Member function address.)

I'm unable to get the same address after passing the pointer to the function.
But as I need the real addresses of the Member functions to verify if both pointers are pointing to the same member function I need the real address...

Further more, converting to (void*) for debug message keep returning warning about converting a member function pointer to a void*. Is there any way to do this without harassing the compiler ?

Once again, I think I am missing something with pointers by lack of knowledge.

Thank you for you help.
Last edited on
In the code you posted, neither GCC or MSVC compilers like this line:
1
2
    std::cout << "From Main1 :: Member function address: " << (void*)&TestClass::func1 << " | Class instance address: "<< (void*)&a << std::endl;


They both say that they cannot perform this cast: (void*)&TestClass::func1
Well here, using GCC it does compile with a simple warning.

But do you know any other way to do it ?

For my main problem, I am still trying to get the real addresses, but each time I try something new GCC return an error... I definitely don't know how to get the class member function address after affecting it to a pointer variable.
Last edited on
The real question is why you want the address of a member function.

While you may be able to get the address of a non-virtual member function, you will not be able to get the address of a virtual member function.
Hum I was not aware of the inability to get the virtual member function address... it's such a big problem then.

Well to answer your question about why I need the address of a member function, here is the answer;

- I need it mainly for my knowledge. Investigating and manipulating code is very important to my point of view...
- So for testing purpose AND for a project I'm working on, I'm trying to make a std::set container of all existing types of function pointers (class member function pointers, static member function pointers, normal function pointers..). And as a std::set need the "operator <", I need to override the "operator <". To make it work, I use the typeid("pointer").name() as first value to compare them, and then I was thinking of using the addresses to compare those with the same typeid...

To store them all in the same std::set I use a modified version of the Object you presented in you "type erasure" article ( http://www.cplusplus.com/forum/articles/18756/ ), using direct reference inside the ObjectModel instead of copying the instance passed as argument. (The "operator <" override is in the Object class as the std::set store Objects, but use the pointers value to reorder Objects.)

Last edited on
Why is the ordering of elements in the container important? Ie, could you not just use a std::deque<> instead?
Well, I think you are printing the address of the function pointer. Instead you have to print the content of the function pointer. I have modified your code slightly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <string>

using namespace std;

class TestClass
{
	public:
	TestClass(){};
	~TestClass(){};
	void func1(string &) {};
};

typedef void (TestClass::*TestType)(string&);

class Foo
{
	public:
	Foo(){};
	~Foo(){};

	template <class C, class T>
	void sendMemberAddress (void(C::*funPtr)(T&), C &obj)
	// without typedef
	{
		cout << "From Foo1 :: Member function address: "
		<< (void *)funPtr << " | Class instance address: "
		<< &obj << endl;
	}

	void sendMemberAddress2 (TestType& funPtr, TestClass& obj)
	// using typedef
	{
		cout << "From Foo2 :: Member function address: "
		<< (void *)funPtr << " | Class instance address: "
		<< &obj << endl;
	}
};

int main()
{
	Foo x;
	TestClass a;

	// Without typedef
	cout << "From Main1 :: Member function address: "
	<< (void *)&TestClass::func1 << " | Class instance address: "
	<< &a << endl;
	x.sendMemberAddress (&TestClass::func1, a);

	// With typedef
	TestType y = &TestClass::func1;
	cout << "From Main2 :: Member function address: "
	<< (void *)y << " (using TestType y = &TestClass::func1)"
	<< endl;
	x.sendMemberAddress2 (y, a);
}



From Main1 :: Member function address: 0x80488f6 | Class instance address: 0xbfb7729e
From Foo1 :: Member function address: 0x80488f6 | Class instance address: 0xbfb7729e
From Main2 :: Member function address: 0x80488f6 (using TestType y = &TestClass::func1)
From Foo2 :: Member function address: 0x80488f6 | Class instance address: 0xbfb7729e


I was using g++ to compile the code. However, the compile was not too happy with the conversion to void *.
@jsmith: I like std::set because of its ability to ensure only one instance of each inserted value (Indeed I can verify myself If the value is already inside a vector or list or deque, but it was interesting to try it out; now I know it's not really easy nor a good idea to try it with a std::set)

Anyway thank you very much for you help, and your good ideas (I particularly like the type erasure).

@krishnendu: Hey ! I tried that but it was crashing all the time ... but with your example and the jsmith informations, I now know why it was crashing... I was trying this with a virtual member function.

So finally:
- I know how to get the address of a function,
- I know how to get the address of a static member function
- I know how to get the address of a non-static, non virtual member function
- I know that I can't get the address of a virtual member function unless I directly put my nose into the vtable.

Thank to all of you for your time and answers, it was very instructive to read your messages in parallel with my own tests and researches.
Topic archived. No new replies allowed.