最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++特殊類設(shè)計(設(shè)計模式)和類型轉(zhuǎn)換方式

 更新時間:2026年05月24日 09:57:13   作者:青瓦夢滋  
本文詳細解析了單例模式、餓漢模式與懶漢模式的設(shè)計方法,并對比了C++中的static_cast、reinterpret_cast與const_cast類型轉(zhuǎn)換方式,同時探討了dynamic_cast在多態(tài)類中的應(yīng)用,為開發(fā)者提供了豐富的設(shè)計模式與類型轉(zhuǎn)換知識

在實際應(yīng)用中,會遇到很多常見的特殊類,本篇會介紹這些類的設(shè)計方式

在這之前,雖然沒有聽過設(shè)計模式,但肯定接觸過設(shè)計模式的例子。

比如迭代器模式,是基于面向?qū)ο笕筇匦灾坏?strong>封裝設(shè)計出來的 ,用迭代器類封裝后,不暴露容器結(jié)構(gòu)的情況下,用統(tǒng)一的方式訪問修改容器中的數(shù)據(jù)

再比如適配器模式,運用了復(fù)用的思想,例如 stack 、 queue 等就是根據(jù)底層容器適配而來的

除此之外,還有工廠模式、裝飾器模式、觀察者模式、單例模式等等,由于大部分設(shè)計模式并不常用,因此本篇只會涉及單例模式

不能被拷貝的對象

對于一個對象的拷貝,只會發(fā)生在拷貝構(gòu)造和賦值重載中,那么只需要把這兩個成員方法禁用即可

class CopyBan
{
    CopyBan(const CopyBan&) = delete;
    CopyBan& operator=(CopyBan) = delete;
public:
    //成員方法
private:
    //成員變量
};

只能在堆上創(chuàng)建的對象

要像該對象只能在堆上被創(chuàng)建,可以將構(gòu)造函數(shù)定義為私有,再用過統(tǒng)一的接口去創(chuàng)建它

class HeapOnly
{
    HeapOnly(const HeapOnly&) = delete;//防止拷貝
public:
    static HeapOnly* HeapGet()
    {
        return new HeapOnly;
    }
private:
    HeapOnly()//構(gòu)造函數(shù)私有化
    {

    }
};

int main()
{
    HeapOnly h1;//報錯
    HeapOnly* h2 = HeapOnly::HeapGet();
    HeapOnly h3 = *h2;//報錯
    return 0;
}

只能在棧上創(chuàng)建的對象

既然只能在棧上創(chuàng)建,只需要把統(tǒng)一接口內(nèi)返回的對象改為棧即可

class StackOnly
{
public:
    static StackOnly StackGet()
    {
        return StackOnly();
    }
private:
    StackOnly()
    {

    }
};

int main()
{
    StackOnly s1 = StackOnly::StackGet();
    StackOnly* s2 = new StackOnly;//報錯
    return 0;
}

還有一種方法是禁用類的專屬operator new,但如果定義static對象時,它是在數(shù)據(jù)段創(chuàng)建的,而不是在棧上,因此有缺陷:

class StackOnly
{
    void* operator new(size_t size) = delete;
public:
private:
};

int main()
{
    StackOnly s1;
    StackOnly* s2 = new StackOnly;//報錯
    static StackOnly s3;//不報錯
    return 0;
}

單例模式

 對于某些類,只應(yīng)該有一個實例化對象,這就稱為單例

單例模式有兩種實現(xiàn)方式:

  • 餓漢模式:類在加載時就創(chuàng)建實例,例如全局變量就可以理解為餓漢模式(定義時就初始化)
  • 懶漢模式:類在第一次使用時再創(chuàng)建實例,一般為調(diào)用getInstance()方法時實例化,它最核心的思想是延時加載,從而優(yōu)化服務(wù)器啟動速度

餓漢舉例:

構(gòu)造和析構(gòu)函數(shù)私有化,防止外部調(diào)用,并禁用拷貝構(gòu)造和賦值重載,就可以防止用戶構(gòu)造對象

//餓漢
template<class T>
class singletonHungry
{
private:
    singletonHungry()
    {
        cout << "將構(gòu)造函數(shù)私有化\n";
    }
    ~singletonHungry()
    {
        cout <<"將析構(gòu)函數(shù)私有化\n";
    }
    //防止使用拷貝構(gòu)造,operator=
    singletonHungry(const singletonHungry&) = delete;
    void operator=(const singletonHungry&) = delete;
public:
    static singletonHungry<T>* getInstance()//static表示該方法屬于類本身,不屬于具體對象
    {
        return &data;
    }
private:
    static singletonHungry<T> data;//唯一對象
};

template<class T>
singletonHungry<T> singletonHungry<T>::data;//靜態(tài)成員需再類外聲明

int main()
{
    singletonHungry<int>* t = singletonHungry<int>::getInstance();
    return 0;
}

懶漢舉例:

在函數(shù)內(nèi)定義局部靜態(tài)變量該變量的生命周期也是隨整個程序,后續(xù)如果再次執(zhí)行定義局部變量的代碼,也會因為已經(jīng)定義過而直接跳過。在多線程中可能存在多個線程同時獲取懶漢單例的情況,因此需要注意線程安全!

//懶漢
template<class T>
class singletonLazy
{
private:
    singletonLazy()
    {
        cout << "將構(gòu)造函數(shù)私有化\n";
    }
    ~singletonLazy()
    {
        cout <<"將析構(gòu)函數(shù)私有化\n";
        
    }
    //防止使用拷貝構(gòu)造,operator=
    singletonLazy(const singletonLazy&) = delete;
    void operator=(const singletonLazy&) = delete;
public:
    
    static singletonLazy<T>& getInstance()//static表示該方法屬于類本身,不屬于具體對象
    {
        static singletonLazy<T> data;//C++11起,局部靜態(tài)變量初始化是線程安全的
        return data;
    }
private:
    //成員
};

int main()
{
    singletonLazy<int>& sl = singletonLazy<int>::getInstance();
    return 0;
}

餓漢和懶漢模式的區(qū)別:

  • 懶漢模式需要考慮線程安全問題,實現(xiàn)相對復(fù)雜;而餓漢模式不需要
  • 懶漢模式是一種懶加載,需要時才會初始化創(chuàng)建對象,不會影響程序的啟動;餓漢模式在程序啟動階段就初始化創(chuàng)建對象,會導(dǎo)致程序啟動慢
  • 如果有多個單例類,有B依賴于A的依賴關(guān)系,就必須要先創(chuàng)建A,才能創(chuàng)建B,此時不能用餓漢,因為餓漢不能確定創(chuàng)建的順序,需要用懶漢模式手動控制
  • 若單例類中使用了線程或動態(tài)庫,由于餓漢模式時類是在main函數(shù)之前創(chuàng)建,此時不能創(chuàng)建線程,并且用不了動態(tài)庫,只能用懶漢模式

C++的類型轉(zhuǎn)換

static_cast/reinterpret_cast

在C語言階段,類型轉(zhuǎn)換分為顯式/隱式類型轉(zhuǎn)換兩種,隱式類型轉(zhuǎn)換作用于意義相近的類型,顯式類型轉(zhuǎn)換(強制類型轉(zhuǎn)換)作用于意義差別大的類型

int i = 1;
double d = 1.5;
i = d;//隱式類型轉(zhuǎn)換

int* pi = nullptr;
pi = i;//報錯
pi = (int*)i;//顯式類型轉(zhuǎn)換

C++不僅兼容C階段的顯式/隱式類型轉(zhuǎn)換,還有自己的一套轉(zhuǎn)換規(guī)范:

  •  static_cast<>() 對應(yīng)C語言的隱式類型轉(zhuǎn)換
  •  reinterpret_cast<>() 對應(yīng)C語言的顯式(強制)類型轉(zhuǎn)換

在轉(zhuǎn)換時,<>中是要轉(zhuǎn)換為的類型,()中是要轉(zhuǎn)換的數(shù)據(jù)

int i = 1;
double d = 1.5;
i = static_cast<int>(d);//隱式類型轉(zhuǎn)換

int* pi = nullptr;
pi = i;//報錯
pi = reinterpret_cast<int*>(i);//顯式類型轉(zhuǎn)換

C++的規(guī)范可以讓可讀性更強

const_cast

 const_cast<>() 用于將const變量在轉(zhuǎn)換時去除const屬性(在C語言中就直接用強轉(zhuǎn))

const int ci = 0;
int* pi1 = const_cast<int*>(&ci);//C++
int* pi2 = (int*)&ci;//C語言階段

但不管是C語言階段還是C++階段,去除const屬性后的變量,再改值也不會應(yīng)用到原變量中

const int ci = 0;
int* pi1 = const_cast<int*>(&ci);//C++
int* pi2 = (int*)&ci;//C語言階段
*pi1 = *pi2 = 5;
cout << *pi1 << ' ' << *pi2 << ' ' << '\n' << ci;
5 5 
0

這是因為讀取帶const屬性的變量時默認在CPU的寄存器中讀取,即使內(nèi)存中的值改變了,但由于讀取時沒有訪問內(nèi)存,直接從寄存器中拿,因此值沒有變,這是編譯器的優(yōu)化機制。

要想禁用這項編譯器優(yōu)化,可以在定義const變量前加上 volatile 關(guān)鍵字

volatile const int ci = 0;
5 5 
5

dynamic_cast

對于繼承類中有虛函數(shù)的類,也就是多態(tài)類,若一個函數(shù)的參數(shù)是父類對象的引用/指針,父子類都可以傳參,若是子類,會發(fā)生切片,這個過程是語法天然支持的(向上轉(zhuǎn)換);若函數(shù)參數(shù)是子類指針/引用,若實參為父類,成功與否要看具體情況(向上轉(zhuǎn)換)

class Parent
{
public:
    virtual void fun()
    {
    }
    int _p;
};

class Child : public Parent
{
public:

    int _c;
};

void funcast(Parent* p)
{
    Child* c = (Child*)p;
    c->_c = 1;
    c->_p = 2;
    cout << c->_c << ' ' << c->_p << '\n';
}

int main()
{
    Parent p;
    Child c;
    funcast(&p);//異常
    funcast(&c);//正常運行
    return 0;
}

 dynamic_cast<>() 用于多態(tài)間的類型轉(zhuǎn)換,它可以取代上面強制類型轉(zhuǎn)換的過程,并且指針轉(zhuǎn)換失敗時返回nullptr,引用轉(zhuǎn)換失敗時報異常

void funcast(Parent* p)
{
    Child* c = dynamic_cast<Child*>(p);
    if(c != nullptr)
    {
        c->_c = 1;
        c->_p = 2;
        cout << c->_c << ' ' << c->_p << '\n';
    }
}

int main()
{
    Parent p;
    Child c;
    funcast(&p);//不會輸出,但不報錯
    funcast(&c);//正常運行
    return 0;
}

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論

枣阳市| 乌鲁木齐县| 明溪县| 湄潭县| 上高县| 天津市| 枣阳市| 全椒县| 秦皇岛市| 重庆市| 乐清市| 都江堰市| 循化| 奉化市| 涞水县| 镇赉县| 桦南县| 乌兰浩特市| 宣武区| 寻甸| 建湖县| 丹东市| 措美县| 吉木乃县| 新疆| 宁安市| 龙川县| 赤水市| 乐业县| 顺昌县| 黑龙江省| 大宁县| 宜春市| 肥西县| 卢氏县| 德清县| 岳普湖县| 琼海市| 芮城县| 普定县| 乐亭县|