C++单个类的所有对象是否共享虚函数表的验证
生活随笔
收集整理的這篇文章主要介紹了
C++单个类的所有对象是否共享虚函数表的验证
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
今天偶然看到這個面試題,第一感覺是既然所有對象共享虛函數(shù)代碼,那么虛函數(shù)指針對所有對象就是一樣的,因此虛函數(shù)表也就是一樣的,沒有必要為每個對象復制一份一模一樣的虛函數(shù)表。所以做個驗證,在這兒記錄一下。如有錯誤,歡迎留言指正,感謝感謝。
1. 單一虛函數(shù)表
驗證代碼如下:
#include <bits/stdc++.h>using namespace std; typedef long long ll; class A { public:A() { cout << "A()" << endl; }virtual void f() { cout << "f()" << endl; }virtual void g() { cout << "g()" << endl; }virtual ~A() { cout << "~A()" << endl; } };typedef void(*Func)();int main() {A a1, a2;ll* vptr;vptr = (ll*)*(ll*)(&a1);cout << "a1虛函數(shù)表地址: "<< vptr << endl;Func f = (Func)(*vptr);cout << "a1.f()地址: " << (ll*)f << endl;f();f = (Func)*(vptr+1);cout << "a1.g()地址: " << (ll*)f << endl;f();vptr = (ll*)*(ll*)(&a2);cout << "a2虛函數(shù)表地址: " << vptr << endl;f = (Func)(*vptr);cout << "a2.f()地址: " << (ll*)f << endl;f();f = (Func)*(vptr + 1);cout << "a2.g()地址: " << (ll*)f << endl;f();return 0; }輸出結(jié)果:
| A() A() a1虛函數(shù)表地址: 00007FF7FB04ADB8 a1.f()地址: 00007FF7FB041456 f() a1.g()地址: 00007FF7FB0414A1 g() a2虛函數(shù)表地址: 00007FF7FB04ADB8 a2.f()地址: 00007FF7FB041456 f() a2.g()地址: 00007FF7FB0414A1 g() ~A() ~A() | A() A() a1虛函數(shù)表地址:0x400f20 a1.f()地址: 0x400d3e f() a1.g()地址: 0x400d6a g() a2虛函數(shù)表地址: 0x400f20 a2.f()地址: 0x400d3e f() a2.g()地址: 0x400d6a g() ~A() ~A() |
輸出f和g的地址以及對f和g進行調(diào)用是為了驗證程序的正確性。無論是VS還是g++,兩個對象的虛函數(shù)表地址都是一樣的,說明兩個對象共享虛函數(shù)表。
2. 多個虛函數(shù)表
既然單一虛函數(shù)表類的對象都共享虛函數(shù)表,那么無論繼承類的對象有多少個虛函數(shù)表,這些虛函數(shù)表應該都是共享的。下面驗證:
#include <bits/stdc++.h>using namespace std; typedef long long ll; class A { public:virtual void fA() { cout << "fA()" << endl; }virtual void gA() { cout << "gA()" << endl; } };class B { public:virtual void fB() { cout << "fB()" << endl; }virtual void gB() { cout << "gB()" << endl; } };class C: public A, public B { };typedef void(*Func)();int main() {C c1, c2;ll* vptr;vptr = (ll*)*(ll*)(&c1);cout << "c1虛函數(shù)表1地址: "<< vptr << endl;Func f = (Func)(*vptr);cout << "c1.fA()地址: " << (ll*)f << endl;f();f = (Func)*(vptr+1);cout << "a1.gA()地址: " << (ll*)f << endl;f();vptr = (ll*)*(ll*)(&c2);cout << "c2虛函數(shù)表1地址: " << vptr << endl;f = (Func)(*vptr);cout << "a2.fA()地址: " << (ll*)f << endl;f();f = (Func)*(vptr + 1);cout << "a2.gA()地址: " << (ll*)f << endl;f();cout << endl;vptr = (ll*)*((ll*)(&c1)+1);cout << "c1虛函數(shù)表2地址: " << vptr << endl;f = (Func)(*vptr);cout << "c1.fB()地址: " << (ll*)f << endl;f();f = (Func)*(vptr + 1);cout << "a1.gB()地址: " << (ll*)f << endl;f();vptr = (ll*)*((ll*)(&c2)+1);cout << "c2虛函數(shù)表2地址: " << vptr << endl;f = (Func)(*vptr);cout << "a2.fB()地址: " << (ll*)f << endl;f();f = (Func)*(vptr + 1);cout << "a2.gB()地址: " << (ll*)f << endl;f();return 0; }輸出如下:
| c1虛函數(shù)表1地址: 00007FF6BACCBE18 c1.fA()地址: 00007FF6BACC12F3 fA() a1.gA()地址: 00007FF6BACC12B7 gA() c2虛函數(shù)表1地址: 00007FF6BACCBE18 a2.fA()地址: 00007FF6BACC12F3 fA() a2.gA()地址:00007FF6BACC12B7 gA() c1虛函數(shù)表2地址: 00007FF6BACCBE38 c1.fB()地址: 00007FF6BACC1244 fB() a1.gB()地址: 00007FF6BACC11DB gB() c2虛函數(shù)表2地址: 00007FF6BACCBE38 a2.fB()地址: 00007FF6BACC1244 fB() a2.gB()地址: 00007FF6BACC11DB gB() | c1虛函數(shù)表1地址: 0x401028 c1.fA()地址: 0x400d76 fA() a1.gA()地址: 0x400da2 gA() c2虛函數(shù)表1地址: 0x401028 a2.fA()地址: 0x400d76 fA() a2.gA()地址: 0x400da2 gA() c1虛函數(shù)表2地址: 0x401048 c1.fB()地址: 0x400dce fB() a1.gB()地址: 0x400dfa gB() c2虛函數(shù)表2地址: 0x401048 a2.fB()地址: 0x400dce fB() a2.gB()地址: 0x400dfa gB() |
可以看出,c1和c2的兩個虛函數(shù)表地址仍然是一樣的。
結(jié)論:如果一個類有虛函數(shù),那么這個類的所有對象共享一個虛函數(shù)表。
總結(jié)
以上是生活随笔為你收集整理的C++单个类的所有对象是否共享虚函数表的验证的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 五种并发包总结
- 下一篇: 【C++复习总结回顾】—— 【五】数组与