vtable和vptr
来源:互联网 发布:rose only和beast 知乎 编辑:程序博客网 时间:2024/05/18 06:27
http://www.dreamincode.net/forums/topic/45816-detail-about-how-vptr-and-virtual-table-works/
这是一个相当牛的帖子。
1. vptr每个对象都会有一个,而vtable是每个类有一个
2. vptr指向了vtable
3. 在C++中,如果一个类有虚函数,那么这个对象的memory layout中就有特个vptr,且在最前面
4. 一个类中就算有多个虚函数,也只有一个vptr
5. 做多重继承,就是继承了多个父类时,就会有多个vptr
6. 看最后一个例子,当子类继承了多个父类,且自己又新加了虚函数,这个vptr是借用了第一个父类的?
Assumption: machine is 32-bit .
Here I am going to explain How Virtual table, Virtual pointer for Virtual functions are internally working.
First we have understand memory layout.
Example 1: How the class's memory layout
01
class Test
02
{
03
public:
04
int data1;
05
int data2;
06
int fun1();
07
};
08
09
int main()
10
{
11
Test obj;
12
cout <<
"obj's Size = "
<< sizeof(obj) << endl;
13
cout <<
"obj 's Address = "
<< &obj << endl;
14
return
0;
15
}
Output:
Sobj's Size = 8
obj 's Address = 0012FF7C
Note: Any Plane member function does not take any memory.
Example 2: Memory Layout of Derived class
01
class Test
02
{
03
public:
04
int a;
05
int b;
06
};
07
08
class dTest : public Test
09
{
10
public:
11
int c;
12
};
13
14
int main()
15
{
16
Test obj1;
17
cout <<
"obj1's Size = "
<< sizeof(obj1) << endl;
18
cout <<
"obj1's Address = "
<< &obj1 << endl;
19
dTest obj2;
20
cout <<
"obj2's Size = "
<< sizeof(obj2) << endl;
21
cout <<
"obj2's Address = "
<< &obj2 << endl;
22
return
0;
23
}
OUTPUT:
obj1's Size = 8
obj1's Address = 0012FF78
obj2's Size = 12
obj2's Address = 0012FF6C
Example 3: Memory layout If we have one virtual function.
01
class Test
02
{
03
public:
04
int data;
05
virtual void fun1()
06
{
07
cout <<
"Test::fun1"
<< endl;
08
}
09
};
10
11
int main()
12
{
13
Test obj;
14
cout <<
"obj's Size = "
<< sizeof(obj) << endl;
15
cout <<
"obj's Address = "
<< &obj << endl;
16
return
0;
17
}
OUTPUT:
obj's Size = 8
obj's Address = 0012FF7C
Note: Adding one virtual function in a class takes 4 Byte extra.
Example 4: More than one Virtual function
01
class Test
02
{
03
public:
04
int data;
05
virtual void fun1() { cout <<
"Test::fun1"
<< endl; }
06
virtual void fun2() { cout <<
"Test::fun2"
<< endl; }
07
virtual void fun3() { cout <<
"Test::fun3"
<< endl; }
08
virtual void fun4() { cout <<
"Test::fun4"
<< endl; }
09
};
10
11
int main()
12
{
13
Test obj;
14
cout <<
"obj's Size = "
<< sizeof(obj) << endl;
15
cout <<
"obj's Address = "
<< &obj << endl;
16
return
0;
17
}
OUTPUT:
obj's Size = 8
obj's Address = 0012FF7C
Note: Adding more virtual functions in a class, no extra size taking i.e. Only one machine size taking(i.e. 4 byte)
Example 5:
01
class Test
02
{
03
public:
04
int a;
05
int b;
06
Test(int temp1 = 0, int temp2 = 0)
07
{
08
a=temp1;
09
b=temp2;
10
}
11
int getA()
12
{
13
return
a;
14
}
15
int getB()
16
{
17
return
b;
18
}
19
virtual ~Test();
20
};
21
22
int main()
23
{
24
Test obj(5, 10);
25
26
// Changing a and b
27
int* pInt = (int*)&obj;
28
*(pInt+0) = 100;
29
*(pInt+1) = 200;
30
31
cout <<
"a = "
<< obj.getA() << endl;
32
cout <<
"b = "
<< obj.getB() << endl;
33
return
0;
34
}
OUTPUT:
a = 200
b = 10
If we Change the code as then
// Changing a and b
int* pInt = (int*)&obj;
*(pInt+1) = 100; // In place of 0
*(pInt+2) = 200; // In place of 1
OUTPUT:
a = 100
b = 200
Note: Who sits 1st place of Class : Answer is VPTR
VPTR - 1st placed in class and rest sits after it.
Example 6:
01
class Test
02
{
03
virtual void fun1()
04
{
05
cout <<
"Test::fun1"
<< endl;
06
}
07
};
08
09
int main()
10
{
11
Test obj;
12
cout <<
"VPTR's Address "
<< (int*)(&obj+0) << endl;
13
cout <<
"VPTR's Value "
<< (int*)*(int*)(&obj+0) << endl;
14
return
0;
15
}
OUTPUT:
VPTR's Address 0012FF7C
VPTR's Value 0046C060
NOTE: This VPTR's value is a address of Virtual table. Lets see in next Example.
Example 7:
01
#include <iostream>
02
using namespace std;
03
04
class Test
05
{
06
virtual void fun1()
07
{
08
cout <<
"Test::fun1"
<< endl;
09
}
10
};
11
typedef void (*Fun)(void);
12
13
int main()
14
{
15
Test obj;
16
cout <<
"VPTR's Address "
<< (int*)(&obj+0) << endl;
17
cout <<
" VIRTUAL TABLE 's Address "
<< (int*)*(int*)(&obj+0) << endl; // Value of VPTR
18
cout <<
"Value at first entry of VIRTUAL TABLE "
<< (int*)*(int*)*(int*)(&obj+0) << endl;
19
20
Fun pFun = (Fun)*(int*)*(int*)(&obj+0); // calling Virtual
function
21
pFun();
22
return
0;
23
}
OUTPUT:
VPTR's Address 0012FF7C
VIRTUAL TABLE 's Address 0046C0EC
Value at first entry of VIRTUAL TABLE 0040100A
Test: fun1
Example 8:
01
class Test
02
{
03
virtual void fun1() { cout <<
"Test::fun1"
<< endl; }
04
virtual void func1() { cout <<
"Test::func1"
<< endl; }
05
};
06
07
int main()
08
{
09
Test obj;
10
11
cout <<
"VPTR's Address "
<< (int*)(&obj+0) << endl;
12
cout <<
"VIRTUAL TABLE 's Address"
<< (int*)*(int*)(&obj+0) << endl;
13
14
// Calling Virtual table functions
15
cout <<
"Value at 1st entry of VTable "
<< (int*)*((int*)*(int*)(&obj+0)+0) << endl;
16
cout <<
"Value at 2nd entry of VTable "
<< (int*)*((int*)*(int*)(&obj+0)+1) << endl;
17
18
return
0;
19
}
OUTPUT:
VPTR's Address 0012FF7C
VIRTUAL TABLE 's Address 0046C0EC
Value at first entry of VIRTUAL TABLE 0040100A
Value at 2nd entry of VIRTUAL TABLE 004012
Example :9
01
class Test
02
{
03
virtual void fun1() { cout <<
"Test::fun1"
<< endl; }
04
virtual void func1() { cout <<
"Test::func1"
<< endl; }
05
};
06
07
typedef void(*Fun)(void);
08
09
int main()
10
{
11
Test obj;
12
Fun pFun = NULL;
13
14
// calling 1st virtual
function
15
pFun = (Fun)*((int*)*(int*)(&obj+0)+0);
16
pFun();
17
18
// calling 2nd virtual
function
19
pFun = (Fun)*((int*)*(int*)(&obj+0)+1);
20
pFun();
21
22
return
0;
23
}
OUTPUT:
Test::fun1
Test::func1
Example 10: multiple Inheritance
01
class Base1
02
{
03
public:
04
virtual void fun();
05
};
06
07
class Base2
08
{
09
public:
10
virtual void fun();
11
};
12
13
class Base3
14
{
15
public:
16
virtual void fun();
17
};
18
19
class Derive : public Base1, public Base2, public Base3
20
{
21
};
22
23
int main()
24
{
25
Derive obj;
26
cout <<
"Derive's Size = "
<< sizeof(obj) << endl;
27
return
0;
28
}
OUTPUT:
Derive's Size = 12
Example 11: Calling Virtual Functions in case of Multiple Inheritance
01
class Base1
02
{
03
virtual void fun1() { cout <<
"Base1::fun1()"
<< endl; }
04
virtual void func1() { cout <<
"Base1::func1()"
<< endl; }
05
};
06
07
class Base2 {
08
virtual void fun1() { cout <<
"Base2::fun1()"
<< endl; }
09
virtual void func1() { cout <<
"Base2::func1()"
<< endl; }
10
};
11
12
class Base3 {
13
virtual void fun1() { cout <<
"Base3::fun1()"
<< endl; }
14
virtual void func1() { cout <<
"Base3::func1()"
<< endl; }
15
};
16
17
class Derive : public Base1, public Base2, public Base3
18
{
19
public:
20
virtual void Fn()
21
{
22
cout <<
"Derive::Fn"
<< endl;
23
}
24
virtual void Fnc()
25
{
26
cout <<
"Derive::Fnc"
<< endl;
27
}
28
};
29
30
typedef void(*Fun)(void);
31
32
int main()
33
{
34
Derive obj;
35
Fun pFun = NULL;
36
37
// calling 1st virtual
function
of Base1
38
pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+0);
39
pFun();
40
41
// calling 2nd virtual
function
of Base1
42
pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);
43
pFun();
44
45
// calling 1st virtual
function
of Base2
46
pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+0);
47
pFun();
48
49
// calling 2nd virtual
function
of Base2
50
pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+1);
51
pFun();
52
53
// calling 1st virtual
function
of Base3
54
pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+0);
55
pFun();
56
57
// calling 2nd virtual
function
of Base3
58
pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+1);
59
pFun();
60
61
// calling 1st virtual
function
of Drive
62
pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);
63
pFun();
64
65
// calling 2nd virtual
function
of Drive
66
pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);
67
pFun();
68
69
return
0;
70
}
OUTPUT:
Base1::fun
Base1::func
Base2::fun
Base2::func
Base3::fun
Base3::func
Drive::Fn
Drive::Fnc
By
Asadullah Ansari
- vtable和vptr
- 多态性——vptr和vtable
- C++中的多态性(vptr和vtable)
- C++中的多态性(vptr和vtable)
- c++多态性——vptr和vtable
- 【转载】多态性——vptr和vtable
- 多态性——vptr和vtable
- c++多态性——vptr和vtable
- C++中的多态性(vptr和vtable)
- 多态性----vptr----vtable
- 多态性----vptr----vtable
- VPTR与Vtable
- 转:多态性----vptr----vtable
- 多态性----vptr----vtable
- 多态性----vptr----vtable
- VPTR和VTABLE和构造函数与继承
- C++中的 虚表(vtable)和虚指针(vptr)
- 【转】C++ 多态性----vptr----vtable
- sql注入及其解决办法
- Hibernate入门(5)
- 也谈正则表达式
- 工作记录
- javascript仿QQ滑动菜单
- vtable和vptr
- 个人管理 - 用blog培养你的思考习惯
- Pojo in Hibernate
- java开发测试工具
- 中国剩余定理
- arm汇编语言调用C函数之参数传递
- FLASH CS5 AS3脚本重制小坦克游戏+源码
- 我比较喜欢的indent配置
- 如何解决:VS2010调试时出现"无法连接到Asp.net Development Server”的问题