日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++单个类的所有对象是否共享虚函数表的验证

發(fā)布時間:2023/12/15 c/c++ 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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é)果:

VS2017 x64平臺Ubuntu1604 64位(g++5.4.0)
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; }

輸出如下:

VS2017 x64平臺Ubuntu1604 64位(g++5.4.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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。