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