Created
May 20, 2017 09:54
-
-
Save owent/90d767e60f383b5e326eb7b1fb615781 to your computer and use it in GitHub Desktop.
VC和GCC成员函数指针实现的研究
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# g++ test4.cpp -g -ggdb -O0 -o test4 && ./test4 | |
# gcc version: 5.4.0 (Ubuntu 16.04 LTS) | |
word size = 8 | |
sizeof vptr = 16 | |
info:15 | |
info:31 | |
info:44 | |
info:44 | |
print:35 | |
11000000000000000000000000000000 => 16 | |
19000000000000000000000000000000 => 16 | |
0C0E4000000000000000000000000000 => 16 | |
11000000000000000000000000000000 => 16 | |
0C0E4000000000000000000000000000 => 16 | |
0C0E4000000000000000000000000000 => 16 | |
0C0E4000000000000800000000000000 => 16 | |
print:35 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ctime> | |
#include <vector> | |
#include <algorithm> | |
#include <cstdio> | |
#include <stdint.h> | |
#include <cstddef> | |
#include <string> | |
#include <cstring> | |
class foo_a | |
{ | |
public: | |
virtual ~foo_a(){} | |
virtual void info() { | |
printf("%s:%d\n", __FUNCTION__, __LINE__); | |
} | |
}; | |
class foo_b | |
{ | |
public: | |
virtual ~foo_b(){} | |
// 这个函数用于试foo_b的结构与foo_a不同 | |
// 以防止VC对foo_a和foo_b的`vcall'{8}'的代码合并 | |
virtual void inspect() { | |
printf("%s:%d\n", __FUNCTION__, __LINE__); | |
} | |
virtual void info() { | |
printf("%s:%d\n", __FUNCTION__, __LINE__); | |
} | |
void print() { | |
printf("%s:%d\n", __FUNCTION__, __LINE__); | |
} | |
}; | |
class foo_c: public foo_a, public foo_b | |
{ | |
public: | |
virtual void info() { | |
printf("%s:%d\n", __FUNCTION__, __LINE__); | |
} | |
}; | |
template<typename T> | |
void dump(void (T::*fn)()) { | |
unsigned char buf[sizeof(fn)]; | |
memcpy(buf, &fn, sizeof(fn)); | |
for(size_t i = 0; i < sizeof(buf); ++ i) { | |
char a = buf[i] >> 4; | |
char b = buf[i] & 0x0F; | |
if (a < 10) { | |
putchar(a + '0'); | |
} else { | |
putchar(a - 10 + 'A'); | |
} | |
if (b < 10) { | |
putchar(b + '0'); | |
} else { | |
putchar(b - 10 + 'A'); | |
} | |
} | |
printf(" => %d\n", (int)sizeof(fn)); | |
} | |
void __attribute__ ((noinline)) run(foo_c* c, void (foo_c::*fn)()){ | |
dump(fn); | |
(c->*fn)(); | |
} | |
int main(int argc, char* argv[]) { | |
void (foo_a::*vptr1)() = &foo_a::info; | |
void (foo_b::*vptr2)() = &foo_b::info; | |
void (foo_b::*ptr)() = &foo_b::print; | |
foo_c c; | |
foo_b b; | |
foo_a a; | |
printf("word size = %d\n", (int)(sizeof(size_t))); | |
printf("sizeof vptr = %d\n", (int)(sizeof(vptr1))); | |
(a.*vptr1)(); | |
(b.*vptr2)(); | |
(c.*vptr1)(); | |
(c.*vptr2)(); | |
(c.*ptr)(); | |
dump(vptr1); | |
dump(vptr2); | |
dump(ptr); | |
dump(&foo_c::info); | |
dump(&foo_c::print); | |
dump(&foo_b::print); | |
foo_c *p = &c; | |
run(p, &foo_c::print); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment