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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【第15章】虚函数

發(fā)布時(shí)間:2023/11/30 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【第15章】虚函数 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、為什么基類中的析構(gòu)函數(shù)要聲明為虛析構(gòu)函數(shù)?

直接的講,C++中基類采用virtual虛析構(gòu)函數(shù)是為了防止內(nèi)存泄漏。具體地說(shuō),如果派生類中申請(qǐng)了內(nèi)存空間,并在其析構(gòu)函數(shù)中對(duì)這些內(nèi)存空間進(jìn)行釋放。假設(shè)基類中采用的是非虛析構(gòu)函數(shù),當(dāng)刪除基類指針指向的派生類對(duì)象時(shí)就不會(huì)觸發(fā)動(dòng)態(tài)綁定,因而只會(huì)調(diào)用基類的析構(gòu)函數(shù),而不會(huì)調(diào)用派生類的析構(gòu)函數(shù)。那么在這種情況下,派生類中申請(qǐng)的空間就得不到釋放從而產(chǎn)生內(nèi)存泄漏。所以,為了防止這種情況的發(fā)生,C++中基類的析構(gòu)函數(shù)應(yīng)采用virtual虛析構(gòu)函數(shù)。?

1. 測(cè)試代碼:?

#include <iostream> #include <memory> using namespace std;class Base { public:Base() { cout << "Base Constructor" << endl; }~Base() { cout << "Base Destructor" << endl; } };class Derived : public Base { public:Derived() { cout << "Derived Constructor" << endl; }~Derived() { cout << "Derived Destructor" << endl; } };int main() {Base* p = new Derived();delete p;return 0; }

輸出結(jié)果:

?

2. 測(cè)試代碼:?

#include <iostream> #include <memory> using namespace std;class Base { public:Base() { cout << "Base Constructor" << endl; }virtual ~Base() { cout << "Base Destructor" << endl; } };class Derived : public Base { public:Derived() { cout << "Derived Constructor" << endl; }virtual ~Derived() { cout << "Derived Destructor" << endl; } };int main() {Base* p = new Derived();delete p;return 0; }

輸出結(jié)果:

?

二、構(gòu)造函數(shù)可以調(diào)用虛函數(shù)嗎?語(yǔ)法上通過(guò)嗎?語(yǔ)義上可以通過(guò)嗎?

#include<string> #include<iostream> using namespace std;class B { public:B(const string& ss) { cout << "B constructor\n"; f(ss); }virtual void f(const string&) { cout << "B::f\n"; } };class D : public B { public:D(const string& ss) :B(ss) { cout << "D constructor\n"; }void f(const string& ss) { cout << "D::f\n"; s = ss; } private:string s; };int main() {D d("Hello"); }

輸出結(jié)果:

分析:

注意,輸出不是D::f 。 究竟發(fā)生了什么?f()是在B::B()中調(diào)用的。如果構(gòu)造函數(shù)中調(diào)用虛函數(shù)的規(guī)則不是如前文所述那樣, 而是如一些人希望的那樣去調(diào)用D::f()。那么因?yàn)闃?gòu)造函數(shù)D::D()尚未運(yùn)行,字符串s還未初始化,所以當(dāng)D::f()試圖將參數(shù) 賦給s時(shí),結(jié)果多半是——立馬當(dāng)機(jī)。

析構(gòu)則正相反,遵循從繼承類到基類的順序(拆房子總得從上往下拆吧?),所以其調(diào)用虛函數(shù)的行為和在構(gòu)造函數(shù)中一樣:虛函數(shù)此時(shí)此刻被綁定到哪里(當(dāng)然應(yīng)該是基類啦——因?yàn)槔^承類已經(jīng)被“拆”了——析構(gòu)了!),調(diào)用的就是哪個(gè)函數(shù)。

有時(shí),這條規(guī)則被解釋為是由于編譯器的實(shí)作造成的。[譯注:從實(shí)作角度可以這樣解釋:在許多編譯器中,直到構(gòu)造函數(shù)調(diào)用完畢,vtable才被建立,此時(shí)虛函數(shù)才被動(dòng)態(tài)綁定至繼承類的同名函數(shù)。] 但事實(shí)上不是這么一回事——讓編譯器實(shí)作成“構(gòu)造函數(shù)中調(diào)用虛函數(shù)也和從其他函數(shù)中調(diào)用一樣”是很簡(jiǎn)單的[譯注:只要把vtable的建立移至構(gòu)造函數(shù)調(diào)用之前即可]。關(guān)鍵還在于語(yǔ)言設(shè)計(jì)時(shí)的考量——讓虛函數(shù)可以求助于基類提供的通用代碼。[譯注:先有雞還是先有蛋?Bjarne實(shí)際上是在告訴你,不是“先有實(shí)作再有規(guī)則”,而是“如此實(shí)作,因?yàn)橐?guī)則如此”。]

總結(jié)

以上是生活随笔為你收集整理的【第15章】虚函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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