Skip to content

Instantly share code, notes, and snippets.

@owent
Created May 20, 2017 09:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save owent/90d767e60f383b5e326eb7b1fb615781 to your computer and use it in GitHub Desktop.
Save owent/90d767e60f383b5e326eb7b1fb615781 to your computer and use it in GitHub Desktop.
VC和GCC成员函数指针实现的研究
# 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
#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