#include <iostream>
class Base
{
public:
Base() { std::cout << "Base()" << std::endl; }
virtual ~Base() { std::cout << "~Base()" << std::endl; }
virtual void
#ifdef _WIN32
__cdecl
#endif
fn(int i) { std::cout << "Base::echo(" << i << ")" << std::endl; }
};
class Derived : public Base {
public:
Derived() : Base() { std::cout << "Derived()" << std::endl; }
virtual ~Derived() { std::cout << "~Derived()" << std::endl; }
virtual void
#ifdef _WIN32
__cdecl
#endif
fn(int i) { std::cout << "Derived::fn(" << i << ")" << std::endl; }
};
int main()
{
#if 1
typedef void(
#ifdef _WIN32
__cdecl
#endif
*TFunction)(void*, int);
Derived d;
Base* p = &d;
// On many platforms, std::size_t is synonymous with std::uintptr_t.
size_t* vptr = reinterpret_cast<size_t*>(p);
size_t* vtable = reinterpret_cast<size_t*>(*vptr);
//p->fn(2); //Error C2248 'Base::fn': cannot access private member declared in class 'Base'
// #ifdef _WIN32
// TFunction invoker = reinterpret_cast<TFunction>(vtable[1]);
// #else
// TFunction invoker = reinterpret_cast<TFunction>(vtable[2]);
// #endif
TFunction invoker = reinterpret_cast<TFunction>(vtable[0]); //destructor
TFunction invoker1 = reinterpret_cast<TFunction>(vtable[1]); //fn
TFunction invoker2 = reinterpret_cast<TFunction>(vtable[2]); //fn1
invoker(p, 0);
invoker1(p, 1);
invoker2(p, 2);
#endif
system("pause");
return 0;
}
#pragma once
#include <iostream>
class Base
{
public:
Base() { std::cout << "Base()" << std::endl; }
virtual ~Base() { std::cout << "~Base()" << std::endl; }
private:
virtual void
#ifdef _WIN32
__cdecl
#endif
fn(int i) { std::cout << "Base::fn(" << i << ")" << std::endl; }
};
class Derived : public Base
{
public:
Derived() : Base() { std::cout << "Derived()" << std::endl; }
virtual ~Derived() { std::cout << "~Derived()" << std::endl; }
// virtual void
// #ifdef _WIN32
// __cdecl
// #endif
// fn(int i) { std::cout << "Derived::fn(" << i << ")" << std::endl; }
private:
virtual void
#ifdef _WIN32
__cdecl
#endif
fn(int i) { std::cout << "Derived::fn(" << i << ")" << std::endl; }
virtual void
#ifdef _WIN32
__cdecl
#endif
fn1(int i) { std::cout << "Derived::fn1(" << i << ")" << std::endl; }
};
#if 0
#include <iostream>
using namespace std;
class Base
{
private:
virtual void f0() { cout << "Base::f0()...." << endl; }
virtual void f1() { cout << "Base::f1()...." << endl; }
virtual void f2() { cout << "Base::f2()...." << endl; }
};
class Derive : public Base {};
typedef void(*Fun)(void);
int main(int argc, char* argv[])
{
Derive d;
Fun pFun0 = (Fun)*((int*)*(int*)(&d) + 0);
Fun pFun1 = (Fun)*((int*)*(int*)(&d) + 1);
Fun pFun2 = (Fun)*((int*)*(int*)(&d) + 2);
pFun0();
pFun1();
pFun2();
return 0;
}
/*
Output:
Base::f0()....
Base::f1()....
Base::f2()....
*/
#endif
#if 0
#include <iostream>
using namespace std;
class Base
{
virtual void g()
{
cout << "Base::g" << endl;
}
virtual void f()
{
cout << "Base::f" << endl;
}
};
class Derived :public Base
{
void g()
{
cout << "Derived::g" << endl;
}
virtual void h()
{
cout << "Derived::h" << endl;
}
};
typedef void(*Fun)(void);
int main(void)
{
Derived d;
Fun pFun = NULL;
for (int i = 0; i < 3; ++i)
{
pFun = (Fun)*((int *)*(int *)(&d) + i);
pFun();
}
return 0;
}
/*VS2010环境下运行结果:
Derived::g
Base::f
Derived::h
结论:
1: 应该有假设“指向虚函数表vtable的虚函数表指针vt_ptr位于位于对象内存块的开始处”;
2 : (Fun)*((int *)*(int *)(&d) + i) : (将指针当做地址)
(&d) : 获得对象d的地址addr1,此地址对应整个对象d的内存块;
(int*)(&d) : 将Derived类型地址addr1强制转换为int类型地址addr2,此地址对应的内存块即为vt_ptr变量;
* (int*)(&d) : 取int类型地址addr2对应内存块中的值,得int类型值val1,该值其实为虚函数表的首地址;
(int*)*(int*)(&d) : 将int类型值val1强制转换为int类型地址addr3,该值即为虚函数表vtable的首地址;
((int*)*(int*)(&d) + i) : 对int类型地址addr3进行算术加,得到虚函数表中元素i的地址addr_i;
* ((int*)*(int*)(&d) + i) : 取int类型地址addr_i对应内存块中的值的int类型值val_i,该值其实为虚函数表中元素i中存储的对应的虚函数的指针;
(Fun)*((int *)*(int *)(&d) + i) : 将int类型值val_i强制转换为Fun类型地址(指针);
论证:
上述讨论中将指针看做地址,其实指针和地址应该是等效的:
int a = 0xAAAABBBB;
int *b = &a;
对以上两个定义语句,a和b都有自己的内存块,假设对应地址值分别为addr_a和addr_b。
则当执行表达式(int *)*b时,意思是将地址值addr_b对应内存块中存储的值(即为地址值addr_a)所对应的内存块中的值0xAAAABBBB强制转换为int*(即int类型指针,也即int类型地址)。
*/
#endif