生活随笔
收集整理的這篇文章主要介紹了
C++基础16-类和对象之联编,重写,虚析构
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1、靜態(tài)聯(lián)編和動態(tài)聯(lián)編
1、聯(lián)編是指一個程序模塊、代碼之間互相關聯(lián)的過程。
2、靜態(tài)聯(lián)編(sta5c binding),是程序的匹配、連接在編譯階段實現(xiàn),也稱為早期匹配。重載函數(shù)使用靜態(tài)聯(lián)編。
3、動態(tài)聯(lián)編是指程序聯(lián)編推遲到運行時進行,所以又稱為晚期聯(lián)編(遲綁定)。switch 語句和 if 語句,多態(tài)是動態(tài)聯(lián)編的例子。
說明:
1、C++與C相同,是靜態(tài)編譯型語言
2、在編譯時,編譯器自動根據(jù)指針的類型判斷指向的是一個什么樣的對象;所以編譯器認為父類指針指向的是父類對象。
3、由于程序沒有運行,所以不可能知道父類指針指向的具體是父類對象還是子類對象,從程序安全的角度,編譯器假設父類指針只指向父類對象,因此編 譯的結果為調用父類的成員函數(shù)。這種特性就是靜態(tài)聯(lián)編。
4、多態(tài)的發(fā)生是動態(tài)聯(lián)編,實在程序執(zhí)行的時候判斷具體父類指針應該調用的方法。
//A.動態(tài)聯(lián)編的基礎是虛函數(shù)
//B.動態(tài)聯(lián)編時在運行時確定所調用的函數(shù)代碼
//C.只有通過基類的指針或引用才能實現(xiàn)動態(tài)聯(lián)編
2、虛析構函數(shù)
構造函數(shù)不能是虛函數(shù)。建立一個派生類對象時,必須從類層次的根開始,沿著繼承路徑逐個調用基類的構造函數(shù)。
析構函數(shù)可以是虛的。虛析構函數(shù)用于指引 delete 運算符正確析構動態(tài) 對象 。
??? 通常用于父類指針指向子類對象時,釋放父類指針時會默認調用父類析構函數(shù),而不會調用子類的析構函數(shù),可能會造成內存泄漏。當把父類的析構函數(shù)定義為虛函數(shù)時,當釋放父類指針時就會發(fā)生多態(tài),先調用子類析構函數(shù),再調用父類構造函數(shù)
3、重載、重寫、重定義
重載(添加):
???????? a 相同的范圍(在同一個類中)
???????? b 函數(shù)名字相同
???????? c 參數(shù)不同 (個數(shù)或類型)
???????? d virtual關鍵字可有可無
重寫(覆蓋) 是指派生類函數(shù)覆蓋基類函數(shù),特征是:
??????? a 不同的范圍,分別位于基類和派生類中
??????? b 函數(shù)的名字相同
??????? c 參數(shù)相同
??????? d 基類函數(shù)必須有virtual關鍵字
重定義(隱藏) 是指派生類的函數(shù)屏蔽了與其同名的基類函數(shù),規(guī)則如下:
?????? a 如果派生類的函數(shù)和基類的函數(shù)同名,但是參數(shù)不同,此時,不管有無virtual,基類的函數(shù)被隱藏。
?????? b 如果派生類的函數(shù)與基類的函數(shù)同名,并且參數(shù)也相同,但是基類函數(shù)沒有vitual關鍵字,此時,基類的函數(shù)被隱藏。
即:重載:同一個作用域下(形參個數(shù)不同,類型不同)
?????? 重寫:如果父類是虛函數(shù),子類在定義一遍。則為重寫(虛函數(shù)重寫)
?????? 重定義:發(fā)生在兩個不同的類中。一個是父類 一個是子類。 //父類普通函數(shù),子類重新寫了一遍(普通函數(shù)定義)
????? ?? ? 即:1、普通函數(shù)重定義? 如果父類的普通成員函數(shù),被子類重寫。說是重定義
???????????? ? ?? 2、虛函數(shù)重寫 如果父類的虛函數(shù),被子類重寫,就是虛函數(shù)重寫。這個函數(shù)會發(fā)生多態(tài)
虛析構函數(shù)代碼示例:
?
#if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#if 0
class A {
public:A() {cout << "A() " << endl;this->p = new char[64];//memset(this->p, 0, 64);strcpy(this->p, "A String...");}virtual void print() {cout << "A的print函數(shù)" << this->p << endl;}~A() {cout << "~A()" << endl;if (this->p != NULL) {delete this->p;this->p = NULL;}}
private:char *p;
};
class B :public A {
public:B() { //會觸發(fā)A的構造函數(shù)cout << "B() " << endl;this->p = new char[64];//memset(this->p, 0, 64);strcpy(this->p, "B String...");}virtual void print() {cout << "B的print函數(shù)" << this->p << endl;}~B() {cout << "~B()" << endl;if (this->p != NULL) { //默認是B的pdelete this->p;this->p = NULL;}}
private:char* p;
};
void func(A *p) {p->print();
}
void test01() {A a; func(&a);cout << "------" << endl;B b;func(&b);
}
/*
A()
A的print函數(shù)A String...
------
A()
B()
B的print函數(shù)B String...
~B()
~A()
~A()
*/
void test02() {B *bp = new B;func(bp);delete bp;
}
/*
A()
B()
B的print函數(shù)B String...
~B()
~A()
*/
void func2(A *p) {p->print(); //發(fā)生多態(tài)delete p; //也應該發(fā)生多態(tài)//此刻觸發(fā)p默認的析構函數(shù)//應該是觸發(fā)誰 調用誰的析構函數(shù) 多態(tài)
}
void test03() {A *ap = new A;func2(ap);
}
/*
A()
A的print函數(shù)A String...
*/
void test04() {B *bp = new B;func2(bp);
}
/*
A()
B()
B的print函數(shù)B String...
~A()
*/
#endif
//在上面的基礎上,將A的析構函數(shù)改為虛函數(shù)
class A {
public:A() {cout << "A() " << endl;this->p = new char[64];//memset(this->p, 0, 64);strcpy(this->p, "A String...");}virtual void print() {cout << "A的print函數(shù)" << this->p << endl;}virtual ~A() {cout << "~A()" << endl;if (this->p != NULL) {delete this->p;this->p = NULL;}}
private:char *p;
};
class B :public A {
public:B() { //會觸發(fā)A的構造函數(shù)cout << "B() " << endl;this->p = new char[64];//memset(this->p, 0, 64);strcpy(this->p, "B String...");}virtual void print() {cout << "B的print函數(shù)" << this->p << endl;}virtual ~B() {cout << "~B()" << endl;if (this->p != NULL) { //默認是B的pdelete this->p;this->p = NULL;}}
private:char* p;
};
void func2(A *p) {p->print();delete p; //此刻觸發(fā)p默認的析構函數(shù)//應該是觸發(fā)誰 調用誰的析構函數(shù) 多態(tài)
}
void test05() {B *bp = new B;func2(bp);
}
/*
A()
B()
B的print函數(shù)B String...
~B()
~A()
*/
int main() {//test01();//test02();//test03();//test04();test05();return 0;
}//重載:同一個作用域下(形參個數(shù)不同,類型不同)
//重寫:如果父類是虛函數(shù),子類在定義一遍。則為重寫(虛函數(shù)重寫)
//重定義:發(fā)生在兩個不同的類中。一個是父類 一個是子類。//父類普通函數(shù),子類重新寫了一遍(普通函數(shù)定義)
//即:1、普通函數(shù)重定義 如果父類的普通成員函數(shù),被子類重寫。說是重定義
// 2、虛函數(shù)重寫 如果父類的虛函數(shù),被子類重寫,就是虛函數(shù)重寫。這個函數(shù)會發(fā)生多態(tài)//A.動態(tài)聯(lián)編的基礎是虛函數(shù)
//B.動態(tài)聯(lián)編時在運行時確定所調用的函數(shù)代碼
//C.只有通過基類的指針或引用才能實現(xiàn)動態(tài)聯(lián)編
#endif
?
總結
以上是生活随笔為你收集整理的C++基础16-类和对象之联编,重写,虚析构的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。