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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

还原virtual函数的本质-----C++

發布時間:2023/12/13 c/c++ 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 还原virtual函数的本质-----C++ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

當你每次看到C++類中聲明一個virtual函數,特別是看到了一個virtual的虛構函數。你知道它的意思嗎?你肯定會毫不猶豫的回答:不就是多態么。。。在運行時確定具體的行為么。。。完全正確,但這里我要講的不只是這些東西。

?有些類需要虛函數,有些不需要虛函數。這是為什么,一般你看到的類如果有一個虛析構函數,那么這個類中應該會有至少一個是虛函數的。。這是為什么呢??如果我們類中沒有用其他虛函數的話,你創建了這個也是多余的,而且會增加類對象的大小。。說這些純理論的東西,也許大家不知所云。。下面我就給例子來驗證。。

1:

?

class A { public:A(){}; // virtual ~A(){};~A(); }; void main() {A a;cout<<sizeof(a)<<endl; }


結果為1。這個1應該是編譯器自己為它加上的。。哪怕你不在類中不寫任何東西,它也是1;例如;

?

?

?

class A {}; void main() {A a;cout<<sizeof(a)<<endl; }


如果你把析構函數聲明為虛函數。。如:

?

?

2:

class A
{
public:
A(){};
virtual ~A(){};
//~A();
};
void main()
{


A a;
cout<<sizeof(a)<<endl;
}

結果是4。先不說這是為什么。。


然后還是說一下關于虛函數基礎的東西(多態)吧,也給個例子:

?

#include<iostream> #include<string> using namespace std;class Base { public:Base();virtual ~Base();virtual void test(); private :int count; }; Base::Base(){cout<<"Base部分創建了"<<endl; } Base::~Base(){cout<<"Base部分被銷毀了"<<endl; } void Base::test() {cout<<"Base Test"<<endl;}class Derive1:public Base { public:Derive1();virtual ~Derive1();void test();}; Derive1::Derive1(){cout<<"子類部分創建了"<<endl; } Derive1::~Derive1(){cout<<"子類部分被銷毀了"<<endl; } void Derive1::test() {cout<<"Derive1 Test"<<endl; }void main() {Base* d1=new Derive1();d1->test();delete d1;}


?

?


由此看見,當通過聲明一個父類指針并且讓它指向一個子類的對象,在子對象創建的時候,會先去調用父類的構造函數,然后再是自己的構造函數,當通過父類指針去調用一個虛函數test()時,它實際上回去調用子類的test()函數,這是為什么呢,它肯定有什么信息讓它這樣做嗎。。這個信息肯定是子類對象給它的。。這個信息就是虛函數指針(vptr),它指向一個虛函數表(vtbl),這個虛函數表其實就是包含了這個類的所有虛函數的函數名(函數指針),每個類就只包含了那一個虛函數指針和它的一些成員變量。這下可以解釋上面為什么是1,為什么是4了。。

?在win32的機器上,每個指針是4字節。剛才也提到每個類的大小取決于兩部分,一個是成員變量,一個是虛函數指針而且有且只有一個,在例子一中,因為沒有成員變量,而有一個虛函數---析構函數,此時肯定會有一個虛函數指針,所以是4。。 其實剛才也就同時說清楚了多態的本質,就是子對象的虛函數指針給出了這個信息,父類指針才知道去執行哪個函數。。

最后一個問題:為什么析構函數要聲明為虛函數呢?(當至少有一個為虛函數的時候)

從剛才的那個結果也可以看出,當我們delete那個指針的時候,會發生析構,而且這個過程是從子類到父類的順序進行。假如此時析構函數不為虛函數,父類指針也就不知道去執行子類的析構函數。。也就不會去釋放子對象的那部分內存,造成內存泄漏。。例如:(這里我們只是對上一段代碼進行修改,去掉了父類中的virtual):

?

#include<iostream> #include<string> using namespace std;class Base { public:Base();~Base();virtual void test(); private :int count; }; Base::Base(){cout<<"Base部分創建了"<<endl; } Base::~Base(){cout<<"Base部分被銷毀了"<<endl; } void Base::test() {cout<<"Base Test"<<endl;}class Derive1:public Base { public:Derive1();~Derive1();void test();}; Derive1::Derive1(){cout<<"子類部分創建了"<<endl; } Derive1::~Derive1(){cout<<"子類部分被銷毀了"<<endl; } void Derive1::test() {cout<<"Derive1 Test"<<endl; }void main() {Base* d1=new Derive1();d1->test();delete d1;}

?

?

所以當至少有一個虛函數的話,我們也要把它的析構函數聲明為virtual。(插一句:有些人會說你子類中的那個函數哪里是虛函數哦,我沒看到virtual 啊。。其實C++允許我們這樣做,重寫父類的虛函數,不是必須要聲明出來的。)

總結:一個類有了虛函數,是為了成為一個基類,如果不是這樣的話,那么父類中的任何函數都沒有必要是虛函數,甚至會增加類的大小。多態告訴了我們這點。。一旦成為了基類,那么就要把析構函數聲明為一個虛函數。。

好了,虛函數的內容就Over了。。。。。

?

轉載于:https://www.cnblogs.com/pangblog/p/3258031.html

總結

以上是生活随笔為你收集整理的还原virtual函数的本质-----C++的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。