1. 程式人生 > >C++筆記 第五十五課 經典問題解析四---狄泰學院

C++筆記 第五十五課 經典問題解析四---狄泰學院

如果在閱讀過程中發現有錯誤,望評論指正,希望大家一起學習,一起進步。
學習C++編譯環境:Linux

第五十五課 經典問題解析四

1.關於動態記憶體分配

new和malloc的區別是什麼?
delete和free的區別是什麼?
new關鍵字與malloc函式的區別
new關鍵字是C++的一部分
malloc是由C庫提供的函式
new以具體型別為單位進行記憶體分配
malloc以位元組為單位進行記憶體分配
new在申請記憶體空間時可進行初始化
malloc僅根據需要申請定量的記憶體空間
下面的程式碼輸出什麼?為什麼?
在這裡插入圖片描述

55-1 new和malloc的區別

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
class Test
{
    int* mp;
public:
    Test()
    {
        cout << "Test::Test()" << endl;
        
        mp = new int(100);
        
        cout << *mp << endl;
    }
    ~Test()
    {
        delete mp;
        
        cout << "~Test::Test()" << endl;
    }
};
int main()
{
    Test* pn = new Test;
    Test* pm = (Test*)malloc(sizeof(Test));
    
    delete pn;
    //free(pn);  //malloc
    //delete pm; //new
    free(pm);
    
    return 0;
}
執行結果
Test::Test()
100
~Test::Test()

new和malloc的區別
new在所有C++編譯器中都被支援
malloc在某些系統開發中是不能呼叫–需要C庫支援
new能夠觸發建構函式的呼叫
malloc僅分配需要的記憶體空間
物件的建立只能使用new
malloc不適合面向物件開發
下面的程式碼輸出什麼?為什麼?—注意成對出現的語句
在這裡插入圖片描述
delete和free的區別
delete在所有C++編譯器中都被支援
free在某些系統開發中是不能呼叫
delete能夠觸發解構函式的呼叫
free僅歸還之前分配的記憶體空間
物件的銷燬只能使用delete
free不適合面向物件開發

2.關於虛擬函式

建構函式是夠可以成為虛擬函式?不可以
解構函式是夠可以成為虛擬函式?可以
建構函式不可能成為虛擬函式
在建構函式執行結束後,虛擬函式表指標才會被正確的初始化
解構函式可以成為虛擬函式
建議在設計類使將解構函式宣告為虛擬函式

55-2 構造,析構,虛擬函式

#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
    Base()
    {
        cout << "Base()" << endl;
        
        func();
    }
    
    virtual void func() 
    {
        cout << "Base::func()" << endl;
    }
    
    virtual ~Base()
    {
        func();
        
        cout << "~Base()" << endl;
    }
};
class Derived : public Base
{
public:
    Derived()
    {
        cout << "Derived()" << endl;
        
        func();
    }
    
    virtual void func()
    {
        cout << "Derived::func()" << endl;
    }
    
    ~Derived()
    {
        func();
        
        cout << "~Derived()" << endl;
    }
};
int main()
{
    Base* p = new Derived();
    
    // ...
    
    delete p;
    
    return 0;
}
執行結果
Base()
Base::func()
Derived()
Derived::func()
Derived::func()
~Derived()
Base::func()
~Base()

建構函式中是夠可以發生多型?不可能
解構函式中是夠可以發生多型?不可能
建構函式中不可能發生多型行為
在建構函式執行時,虛擬函式表指標未被正確初始化
解構函式中不可能發生多型行為
在解構函式執行時,虛擬函式表指標已經被銷燬
建構函式和解構函式中不能發生多型行為,只調用當前類中定義的函式版本!!

3.關於繼承中的強制型別轉換

繼承中如何正確的使用強制型別轉換?
dynamic_cast是與繼承相關的型別轉換關鍵字
dynamic_cast要求相關的類中必須有虛擬函式
用於有直接或者間接繼承關係的指標(引用)之間
指標:
轉換成功:得到目標型別的指標
轉換失敗:得到一個空指標
引用:
轉換成功:得到目標型別的引用
轉換失敗:得到一個異常操作資訊
編譯器會檢查dynamic_cast的使用是否正確
型別轉換的結果只可能在執行階段才能得到

55-3 dynamic_cast

列印Cast error的原因:不能用子類的指標指向一個父類的物件
#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
    Base()
    {
        cout << "Base::Base()" << endl;
    }
    
    virtual ~Base()
    {
        cout << "Base::~Base()" << endl;
    }
};
class Derived : public Base
{
};
int main()
{
    Base* p = new Base;
    
    Derived* pd = dynamic_cast<Derived*>(p);
    
    if( pd != NULL )
    {
        cout << "pd = " << pd << endl;
    }
    else
    {
        cout << "Cast error!" << endl;
    }
    
    delete p;
    
    return 0;
}
執行結果
Base::Base()
Cast error!
Base::~Base()

小結
new/delete會觸發建構函式或者解構函式的呼叫
建構函式不能成為虛擬函式
解構函式可以成為虛擬函式
建構函式和解構函式中無法產生多型行為
dynamic_cast是與繼承相關的專用轉換關鍵字