国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

cpp_07_類型轉(zhuǎn)換構(gòu)造_析構(gòu)函數(shù)_深拷貝_靜態(tài)成員

這篇具有很好參考價(jià)值的文章主要介紹了cpp_07_類型轉(zhuǎn)換構(gòu)造_析構(gòu)函數(shù)_深拷貝_靜態(tài)成員。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

cpp_07_類型轉(zhuǎn)換構(gòu)造_析構(gòu)函數(shù)_深拷貝_靜態(tài)成員,Cpp,c++

1? 類型轉(zhuǎn)換構(gòu)造函數(shù)

1.1? why?

? ? ? ? 基本類型之間的轉(zhuǎn)換,編譯器內(nèi)置轉(zhuǎn)換規(guī)則:int -> double

? ? ? ? 類類型之間的轉(zhuǎn)換,編譯器不知道轉(zhuǎn)換規(guī)則,需要用戶提供:Cat -> Dog

// consconv_why.cpp 為什么需要自定義轉(zhuǎn)換
#include <iostream>
using namespace std;

class Cat {
public:
    Cat( const char* name ) : m_name(name) {
        //【string m_name(name);】
    }
    void talk( ) {
        cout << m_name << ": 喵喵~~~" << endl;
    }
private:
    string m_name;
};

class Dog {
public:
    Dog( const char* name ) : m_name(name) {
        //【string m_name(name);】
    }
    void talk( ) {
        cout << m_name << ": 汪汪~(yú)~~" << endl;
    }
private:
    string m_name;
};
// 模擬類的設(shè)計(jì)者(類庫(kù)、別人設(shè)計(jì)的類、自己設(shè)計(jì)的類)
// --------------------------------
// 模擬用戶(使用類的人)
int main( void ) {
    Cat smallwhite("小白");
    smallwhite.talk( );

    Dog bigyellow = smallwhite; // Cat --> Dog

    return 0;
}

1.2? 理論

? ? ? ? 定義:1)單參構(gòu)造? ? ? ? ? ? ? ? ? ? ? ? ? ? (同于拷貝構(gòu)造函數(shù))? ?

? ? ? ? ? ? ? ? ? ?2)參數(shù)類型與類類型不同? ? ? (異于拷貝構(gòu)造函數(shù))

? ? ? ? (單參構(gòu)造就2種,參數(shù)類型同于類類型,就是拷貝構(gòu)造,否則就是類型轉(zhuǎn)換構(gòu)造)

? ? ? ? class? ?目標(biāo)類型 {

? ? ? ? ? ? ? ? ? ?目標(biāo)類型 ( const? 源類型&? src ) { ... }? // 類型轉(zhuǎn)換構(gòu)造函數(shù)

? ? ? ? ? ? ? ? ? ? };

? ? ? ? 用于:

? ? ? ? 1)利用一個(gè)已定義的對(duì)象,來(lái)定義另一個(gè)不同類型的對(duì)象

? ? ? ? 2)實(shí)現(xiàn)從源類型到目標(biāo)類型的隱式類型轉(zhuǎn)換?

? ? ? ? 通過(guò)explicit關(guān)鍵字,可以強(qiáng)制? 這種通過(guò)類型轉(zhuǎn)換構(gòu)造函數(shù)實(shí)現(xiàn)的類型轉(zhuǎn)換? 必須通過(guò)靜態(tài)轉(zhuǎn)換顯示地進(jìn)行:

? ? ? ? class? 目標(biāo)類型 {

? ? ? ? ? ? ? ? explicit? 目標(biāo)類型 ( const? 源類型&? src ) { ... };

? ? ? ? };

// consconv.cpp
// 類型轉(zhuǎn)換構(gòu)造函數(shù) -- 指定 源類型 到 目標(biāo)類型 的 轉(zhuǎn)換規(guī)則
#include <iostream>
using namespace std;

class Cat {
public:
    explicit Cat( const char* name ) : m_name(name) { // 類型轉(zhuǎn)換構(gòu)造函數(shù)
        //【string m_name(name);】
        cout << "Cat類的類型轉(zhuǎn)換構(gòu)造函數(shù)被調(diào)用" << endl;
    }
    void talk( ) {
        cout << m_name << ": 喵喵~~~" << endl;
    }
private:
    string m_name;
    friend class Dog; // 友元聲明
};

class Dog {
public:
    Dog( const char* name ) : m_name(name) { // 類型轉(zhuǎn)換構(gòu)造函數(shù)
        //【string m_name(name);】
    }
    explicit Dog( const Cat& c ) : m_name(c.m_name) { // 類型轉(zhuǎn)換構(gòu)造函數(shù)(Cat-->Dog的轉(zhuǎn)換規(guī)則)
        //【string m_name=c.m_name;】
        cout << "Dog類的類型轉(zhuǎn)換構(gòu)造函數(shù)被調(diào)用" << endl;
    }
    void talk( ) {
        cout << m_name << ": 汪汪~(yú)~~" << endl;
    }
private:
    string m_name;
};
// 模擬類的設(shè)計(jì)者(類庫(kù)、別人設(shè)計(jì)的類、自己設(shè)計(jì)的類)
// --------------------------------
// 模擬用戶(使用類的人)
int main( void ) {
//  Cat smallwhite("小白"); // 定義smallwhite,利用smallwhite.Cat("小白")->類型轉(zhuǎn)換構(gòu)造函數(shù)

//  Cat smallwhite = "小白"; // 定義 匿名Cat類對(duì)象,利用 匿名Cat類對(duì)象.Cat("小白")->隱式轉(zhuǎn)換
                             // Cat smallwhite=匿名Cat類對(duì)象-->克隆
   
    Cat smallwhite = static_cast<Cat>("小白"); 
                             // 定義 匿名Cat類對(duì)象,利用 匿名Cat類對(duì)象.Cat("小白")->靜態(tài)轉(zhuǎn)換
                             // Cat smallwhite=匿名Cat類對(duì)象-->克隆
    smallwhite.talk( );

//    Dog bigyellow(smallwhite); // 定義bigyellow,利用bigyellow.Dog(smallwhite)->類型轉(zhuǎn)換構(gòu)造函數(shù)

//    Dog bigyellow = smallwhite; // 定義 匿名Dog類對(duì)象,利用 匿名Dog類對(duì)象.Dog(smallwhite)->隱式類型轉(zhuǎn)換
                                // Dog bigyellow = 匿名Dog類對(duì)象-->克隆
    Dog bigyellow = static_cast<Dog>(smallwhite); 
                                    // 定義 匿名Dog類對(duì)象,利用 匿名Dog類對(duì)象.Dog(smallwhite)->靜態(tài)類型轉(zhuǎn)換
                                    // Dog bigyellow = 匿名Dog類對(duì)象-->克隆
    bigyellow.talk( );
    return 0;
}

2? 析構(gòu)函數(shù)

2.1? 理論

????????析構(gòu)函數(shù)的函數(shù)名就是在類名前面加“~”,沒(méi)有返回類型沒(méi)有參數(shù),不能重載。

? ? ? ? 在銷毀對(duì)象之前一刻自動(dòng)被調(diào)用,且僅被調(diào)用一次?:

? ? ? ? ? ? ? ? - 對(duì)象離開(kāi)作用域? ?(棧對(duì)象離開(kāi)main函數(shù))

? ? ? ? ? ? ? ? - delete操作符? ? ? ? (堆對(duì)象被釋放)

? ? ? ? 作用:銷毀? 對(duì)象的各個(gè)成員變量?

? ? ? ? 如果一個(gè)類沒(méi)有定義析構(gòu)函數(shù),那么編譯器會(huì)為其提供一個(gè)默認(rèn)的析構(gòu)函數(shù):

? ? ? ? ? ? ? ? - 對(duì)基本類型的成員變量,什么也不做。

? ? ? ? ? ? ? ? - 對(duì)類類型的成員變量,調(diào)用相應(yīng)類型的析構(gòu)函數(shù)。

? ? ? ? ? ? ? ? - 銷毀 對(duì)象的各個(gè)成員變量?

2.2? 析構(gòu)過(guò)程

????????cpp_07_類型轉(zhuǎn)換構(gòu)造_析構(gòu)函數(shù)_深拷貝_靜態(tài)成員,Cpp,c++

? ? ? ? 對(duì)象的銷毀過(guò)程:

????????1)調(diào)用析構(gòu)函數(shù)(陷)

? ? ? ? ? ? ? ? - 執(zhí)行自己在析構(gòu)函數(shù)中書(shū)寫(xiě)的代碼?

? ? ? ? ? ? ? ? - 利用類成員變量調(diào)用相應(yīng)的析構(gòu)函數(shù)?

? ? ? ? ? ? ? ? - 釋放對(duì)象的各成員變量所占內(nèi)存空間?

? ? ? ? 2)釋放整個(gè)對(duì)象所占用的內(nèi)存空間 (皮)

// 析構(gòu)函數(shù)
#include <iostream>
using namespace std;

class Human {
public:
//  如果類沒(méi)有提供任何構(gòu)造函數(shù),編譯器將提供一個(gè)無(wú)參的構(gòu)造函數(shù)
/*  Human() {
       【int m_age;】定義m_age,初值為隨機(jī)數(shù)
       【string m_name;】定義m_name,利用m_name.string()
    }*/
    Human( int age=0, const char* name="無(wú)名" ) : m_age(age),m_name(name) {
        //【int m_age=age;】定義m_age,初值為age
        //【string m_name(name);】定義m_name,利用m_name.string(name)
        cout << "Human類缺省構(gòu)造函數(shù)被調(diào)用" << endl;
    }
//  如果類沒(méi)有提供拷貝構(gòu)造函數(shù),編譯器將提供一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù)
/*  Human( const Human& that ) { 
       【int m_age=that.m_age;】定義m_age,初值為that.m_age
       【string m_name(that.m_name);】定義m_name,利用m_name.string(that.m_name)-->string類拷貝構(gòu)造函數(shù)
    }*/
    Human( const Human& that ) : m_age(that.m_age), m_name(that.m_name) { 
        //【int m_age=that.m_age;】定義m_age,初值為that.m_age
        //【string m_name(that.m_name);】定義m_name,利用m_name.string(that.m_name)
        cout << "Human類拷貝構(gòu)造函數(shù)被調(diào)用" << endl;
    }
//  如果類沒(méi)有提供拷貝賦值函數(shù),編譯器將提供一個(gè)默認(rèn)的拷貝賦值函數(shù)
/*  Human& operator=( const Human& that ) {
        this->m_age = that.m_age;
        this->m_name = that.m_name; // this->m_name.operator=(that.m_name)-->string類的拷貝賦值函數(shù)
        return *this;
    }*/
    Human& operator=( const Human& that ) {
        // 編譯器不會(huì)再拷貝賦值函數(shù)中塞任何操作
        cout << "Human類的拷貝賦值函數(shù)被調(diào)用" << endl;
        this->m_age = that.m_age;
        this->m_name = that.m_name; // this->m_name.operator=(that.m_name)-->string類的拷貝賦值函數(shù)
        return *this;
    }
//  如果類沒(méi)有提供析構(gòu)函數(shù),編譯器將提供一個(gè)默認(rèn)的析構(gòu)函數(shù)
/*  ~Human() {
        對(duì)于基本類型成員變量m_age,什么都不做
        對(duì)于類類型成員變量m_name,利用 m_name.~string()
        釋放 m_age/m_name 本身所占內(nèi)存空間
    }*/
    
    ~Human() {
        cout << "Human類的析構(gòu)函數(shù)被調(diào)用" << endl;
        // 對(duì)于基本類型成員變量m_age,什么都不做
        // 對(duì)于類類型成員變量m_name,利用 m_name.~string()
        // 釋放 m_age/m_name 本身所占內(nèi)存空間
    }
    void getinfo( ) {
        cout << "姓名: " << m_name << ", 年齡: " << m_age << endl;
    }
private:
    int m_age; // 基本類型的成員變量
    string m_name; // 類類型的成員變量
};

// 模擬類的設(shè)計(jì)者(類庫(kù)、別人設(shè)計(jì)的類、自己設(shè)計(jì)的類)
// --------------------------------
// 模擬用戶(使用類的人)
int main( void ) {
    Human h; // 定義h,利用h.Human()-->h維護(hù)的內(nèi)容為(無(wú)名,0)
    h.getinfo( );

    Human h2(22,"張飛"); // 定義h2,利用h2.Human(22,"張飛")-->h2維護(hù)的內(nèi)容為(張飛,22)
    h2.getinfo();

    Human h3(h2); // = h2; // 定義h3,利用h3.Human(h2)-->觸發(fā)拷貝構(gòu)造函數(shù)
    h3.getinfo();

    Human h4; // 定義h4,利用h4.Human()-->h4維護(hù)的內(nèi)容為(無(wú)名,0)
    cout << "h4被賦值前---";
    h4.getinfo();

    h4 = h3; // h4.operator=(h3)-->觸發(fā)拷貝賦值函數(shù)
    cout << "h4被賦值后---";
    h4.getinfo();
    cout << "------------main will be over----------------" << endl;
    return 0;
} //(1) h.~Human() h2.~Human() h3.~Human() h4.~Human() (2)釋放h/h2/h3/h4本身所占的內(nèi)存空間
  //(1) 刪餡                                           (2)刪皮

2.3? has to

? ? ? ? 通常情況下,若對(duì)象在其聲明周期的最終時(shí)刻,并不持有任何動(dòng)態(tài)分配的資源,可以不定義析構(gòu)函數(shù)。

? ? ? ? 若對(duì)象在其聲明周期的最終時(shí)刻,持有動(dòng)態(tài)資源,則必須定義析構(gòu)函數(shù),釋放對(duì)象所持有的動(dòng)態(tài)資源。

// hastodes必須自己寫(xiě)析構(gòu)函數(shù)的情況 -- 對(duì)象臨死時(shí),持有動(dòng)態(tài)資源
#include <iostream>
using namespace std;

class A {
public:
    A(int i) : m_i(i), m_p(new int), m_f(open("./file", O_CREAT|O_RDWR,0644)) {
        //【int m_i=i;】定義m_i,初值為i
        //【int* m_p=new int;】定義m_p,初值為指向一塊堆內(nèi)存(動(dòng)態(tài)資源)
        //【int m_f=open(...);】定義m_f,初值為文件描述符-->文件表等內(nèi)核結(jié)構(gòu)(動(dòng)態(tài)資源)
    }
    ~A() {
        delete m_p;
        close( m_f ); // 動(dòng)態(tài)資源需要自己寫(xiě)代碼釋放

        // 釋放m_i / m_p / m_f 本身所占內(nèi)存空間
    }
    /* 默認(rèn)析構(gòu)函數(shù)
    ~A() {
        釋放m_i / m_p / m_f 本身所占內(nèi)存空間
    }
    */
private:
    int m_i;
    int* m_p;
    int m_f;
};
// 模擬類的設(shè)計(jì)者(類庫(kù)、別人設(shè)計(jì)的類、自己設(shè)計(jì)的類)
// --------------------------------
// 模擬用戶(使用類的人)
int main( void ) {
    A a; // 定義a,利用a.A()
    return 0;
} // a.~A()  釋放a本身所占內(nèi)存空間

? ? ? ? 析構(gòu)函數(shù)的功能并不局限在釋放資源上,它還可以執(zhí)行? 我們希望在? 對(duì)象被釋放之前? 執(zhí)行的任何操作。?

3? 深拷貝

3.1? 淺拷貝缺陷

? ? ? ? 如果類不提供拷貝構(gòu)造,編譯器將提供默認(rèn)的拷貝構(gòu)造。

? ? ? ? 無(wú)論是??拷貝構(gòu)造??還是??拷貝賦值,其默認(rèn)實(shí)現(xiàn),對(duì)任何類型的指針成員都是簡(jiǎn)單地復(fù)制地址,而并不復(fù)制地址指向的數(shù)據(jù),這種情況稱為淺拷貝。(左圖)

? ? ? ? 為了獲得完整意義上的對(duì)象副本,必須自己定義??拷貝構(gòu)造? 和? 拷貝賦值,針對(duì)指針型成員變量做深拷貝。(右圖)

?????????cpp_07_類型轉(zhuǎn)換構(gòu)造_析構(gòu)函數(shù)_深拷貝_靜態(tài)成員,Cpp,c++??cpp_07_類型轉(zhuǎn)換構(gòu)造_析構(gòu)函數(shù)_深拷貝_靜態(tài)成員,Cpp,c++

// copybytes_pre.cpp 類中有指針成員,默認(rèn)拷貝構(gòu)造 會(huì)有淺拷貝缺陷
#include <iostream>
#include <cstring>
using namespace std;
// 模擬C++標(biāo)準(zhǔn)的string類 實(shí)現(xiàn)自己的String類
class String {
public:
    String( const char* psz="" ) : m_psz(new char[strlen(psz)+1]) {
        //【char* m_psz=new char[strlen(psz)+1];】// 動(dòng)態(tài)資源
        strcpy( m_psz, psz );
    }
    ~String( /* String* this */ ) {
        delete[] this->m_psz;
        // 釋放 m_psz 本身所占內(nèi)存空間
    }
    char* c_str() { return m_psz; }
//  默認(rèn)的拷貝構(gòu)造
/*  String( const String& that ) {
        【char* m_psz = that.m_psz;】只復(fù)制了地址,沒(méi)有復(fù)制地址指向的數(shù)據(jù)-->淺拷貝
    }*/ 
private:
    char* m_psz;
};
// 模擬類的設(shè)計(jì)者(類庫(kù)、別人設(shè)計(jì)的類、自己設(shè)計(jì)的類)
// --------------------------------
// 模擬用戶(使用類的人)
int main( void ) {
    String s1("hello");
    cout << "s1:" << s1.c_str() << ", s1中的m_psz指向的堆內(nèi)存的地址: " << (void*)s1.c_str() << endl;

    String s2(s1); // = s1; 定義s2,利用s2.String(s1)-->拷貝構(gòu)造函數(shù)
    cout << "s2:" << s2.c_str() << ", s2中的m_psz指向的堆內(nèi)存的地址: " << (void*)s2.c_str() << endl;
    return 0;
} // s1.~String()  s2.~String() 

????????相對(duì)于拷貝構(gòu)造,拷貝賦值需要做更多的工作:

? ? ? ? ? ? ? ? - 避免自賦值

? ? ? ? ? ? ? ? - 分配新資源

? ? ? ? ? ? ? ? - 拷貝新內(nèi)容

? ? ? ? ? ? ? ? - 釋放舊資源

? ? ? ? ? ? ? ? - 返回自引用

// copybytes.cpp 類中有指針成員,默認(rèn)拷貝構(gòu)造 會(huì)有淺拷貝缺陷
#include <iostream>
#include <cstring>
using namespace std;
// 模擬C++標(biāo)準(zhǔn)的string類 實(shí)現(xiàn)自己的String類
class String {
public:
    String( const char* psz="" ) : m_psz(new char[strlen(psz)+1]) {
        //【char* m_psz=new char[strlen(psz)+1];】// 動(dòng)態(tài)資源
        strcpy( m_psz, psz );
    }
    ~String( /* String* this */ ) {
        delete[] this->m_psz;
        // 釋放 m_psz 本身所占內(nèi)存空間
    }
    char* c_str() { return m_psz; }
//  默認(rèn)的拷貝構(gòu)造
/*  String( const String& that ) {
        【char* m_psz = that.m_psz;】只復(fù)制了地址,沒(méi)有復(fù)制地址指向的數(shù)據(jù)-->淺拷貝
    }*/
    // 深拷貝構(gòu)造函數(shù)
    String( const String& that ) : m_psz(new char[strlen(that.m_psz)+1]) {
        //【char* m_psz = new char[strlen(that.m_psz)+1];】
        strcpy( m_psz, that.m_psz ); // 不復(fù)制地址,復(fù)制地址指向的數(shù)據(jù)-->深拷貝
    }
    /* 默認(rèn)拷貝賦值函數(shù)
    String& operator=( const String& that ) {
        this->m_psz = that.m_psz; // 只復(fù)制了地址,沒(méi)有復(fù)制地址指向的數(shù)據(jù)-->淺拷貝
        return *this;
    }
    */
    // 深拷貝賦值函數(shù)
    String& operator=( const String& that ) {
        if( this != &that ) { // 防止自賦值
            delete[] this->m_psz; // 釋放舊資源
            this->m_psz = new char[strlen(that.m_psz)+1]; // 分配新資源
            strcpy( this->m_psz, that.m_psz ); // 拷貝新內(nèi)容
        }
        return *this; // 返回自引用
    }
private:
    char* m_psz;
};
// 模擬類的設(shè)計(jì)者(類庫(kù)、別人設(shè)計(jì)的類、自己設(shè)計(jì)的類)
// --------------------------------
// 模擬用戶(使用類的人)
int main( void ) {
    String s1("hello");
    cout << "s1:" << s1.c_str() << ", s1中的m_psz指向的堆內(nèi)存的地址: " << (void*)s1.c_str() << endl;

    String s2(s1); // = s1; 定義s2,利用s2.String(s1)-->拷貝構(gòu)造函數(shù)
    cout << "s2:" << s2.c_str() << ", s2中的m_psz指向的堆內(nèi)存的地址: " << (void*)s2.c_str() << endl;

    String s3; // 定義s3,利用s3.String()-->s3維護(hù)一個(gè)字節(jié)堆內(nèi)存('\0')
    s3 = s2; // s3.operator=(s2)
    cout << "s3:" << s3.c_str() << ", s3中的m_psz指向的堆內(nèi)存的地址: " << (void*)s3.c_str() << endl;

    return 0;
} // s1.~String()  s2.~String() 

3.2? 建議

? ? ? ? 1)只有類中有指針型成員變量,才會(huì)涉及深淺拷貝的問(wèn)題,因此應(yīng)盡量避免使用指針型成員變量。

? ? ? ? 2)如果確實(shí)無(wú)法實(shí)現(xiàn)完整意義上的? 深拷貝拷貝構(gòu)造? 和? 深拷貝拷貝賦值,可將它們私有化,禁止用戶使用。

4? 靜態(tài)成員

4.1? 靜態(tài)成員變量

? ? ? ? 靜態(tài)成員變量? 不屬于對(duì)象? 而? 屬于類

? ? ? ? ? ? ? ? - 靜態(tài)成員變量不包含在對(duì)象中,進(jìn)程級(jí)生命期

? ? ? ? ? ? ? ? - 靜態(tài)成員變量的定義和初始化,只能在類的外部(即全局域)而不能在構(gòu)造函數(shù)中進(jìn)行。

? ? ? ? ? ? ? ? - 靜態(tài)成員變量依然受? 類作用域? 和? 訪問(wèn)控制限定符? 的約束。

? ? ? ? ? ? ? ? - 訪問(wèn)靜態(tài)成員變量,既可以通過(guò)? 類? 也可以通過(guò)? 對(duì)象。

? ? ? ? ? ? ? ? - 靜態(tài)成員變量為該類的所有對(duì)象實(shí)例所共享

// static.cpp 類的靜態(tài)成員變量
#include <iostream>
using namespace std;

// 普通成員變量:屬于對(duì)象,對(duì)象的生命期      靜態(tài)成員變量:不屬于對(duì)象,進(jìn)程級(jí)生命期
class A {
public:
    A() {
        //【int m_i;】
    }
    int m_i; // 聲明
    static int m_si; // 聲明
};
int A::m_si = 0; // 全局域中定義-->進(jìn)程級(jí)生命期
// 模擬類的設(shè)計(jì)者(類庫(kù)、別人設(shè)計(jì)的類、自己設(shè)計(jì)的類)
// --------------------------------
// 模擬用戶(使用類的人)
int main( void ) {
    A a, b; // 靜態(tài)成員變量沒(méi)有保存在對(duì)象內(nèi)部-->不屬于對(duì)象
    cout << "a對(duì)象的大小:" << sizeof(a) << endl; // 4
    cout << "b對(duì)象的大小:" << sizeof(b) << endl; // 4

    A::m_si = 888; // 靜態(tài)成員受到類作用域的約束 也受到訪問(wèn)控制限定符的約束-->屬于類

    a.m_si = 999; // A::m_si=999;
    cout << "b.m_si=" << b.m_si << endl; // A::m_si
    // 類的靜態(tài)成員變量,被該類的所有對(duì)象共享
    return 0;
}

4.2? 靜態(tài)成員函數(shù)

? ? ? ? 靜態(tài)成員函數(shù)? 不屬于對(duì)象(普通成員函數(shù)也不屬于對(duì)象,更準(zhǔn)確地說(shuō),不用非要對(duì)象來(lái)調(diào))? 而? 屬于類

? ? ? ? ? ? ? ? - 靜態(tài)成員函數(shù)沒(méi)有this指針,也沒(méi)有常屬性??

? ? ? ? ? ? ? ? - 靜態(tài)成員函數(shù)依然受? 類作用域? 和? 訪問(wèn)控制限定符的約束

? ? ? ? ? ? ? ? - 訪問(wèn)靜態(tài)成員函數(shù),既可以通過(guò)? 類? 也可以通過(guò)? 對(duì)象。(普通成員函數(shù),只對(duì)象)

? ? ? ? ? ? ? ? -靜態(tài)成員函數(shù)只能訪問(wèn)靜態(tài)成員,而非靜態(tài)成員函數(shù)可以訪問(wèn)所有成員。

// static.cpp 類的 靜態(tài)成員變量 和 靜態(tài)成員函數(shù)
#include <iostream>
using namespace std;

// 普通成員函數(shù):必須利用對(duì)象來(lái)調(diào)用      靜態(tài)成員函數(shù):不是必須利用對(duì)象來(lái)調(diào)用
class A {
public:
    int m_i; // 普通成員變量
    void foo( /* const A* this */ ) const { // 普通成員函數(shù)
        cout << "foo is invoked" << endl;
        cout << m_i << endl; // ok
        cout << m_si << endl;// ok
        bar();               // ok
//      以上三行代碼證明 非靜態(tài)成員函數(shù) 即可訪問(wèn)非靜態(tài)成員 也可訪問(wèn) 靜態(tài)成員(不挑食)
    }

    static int m_si; //靜態(tài)成員變量
    static void bar( /*無(wú)this指針*/ ) /*const*/ { // 靜態(tài)成員函數(shù)
        cout << "bar is invoked" << endl;
        cout << m_si << endl; // ok
//      cout << m_i << endl;  // error
//      foo();                // error
//      以上三行代碼證明 靜態(tài)成員函數(shù) 只能訪問(wèn) 靜態(tài)成員,不能訪問(wèn)非靜態(tài)的普通成員(挑食)
    }
};
int A::m_si = 0; // 全局域中定義-->進(jìn)程級(jí)生命期
// 模擬類的設(shè)計(jì)者(類庫(kù)、別人設(shè)計(jì)的類、自己設(shè)計(jì)的類)
// --------------------------------
// 模擬用戶(使用類的人)
int main( void ) {
    A a, b;
    a.foo(); // foo(&a);
    b.foo(); // foo(&b);

    A::bar(); // 受到類作用域的約束 也受到訪問(wèn)控制限定符的約束-->屬于類
    a.bar(); // A::bar();
    b.bar(); // A::bar();
    return 0;
}

4.3? 總結(jié)

????????????????????????????????????????????????cpp_07_類型轉(zhuǎn)換構(gòu)造_析構(gòu)函數(shù)_深拷貝_靜態(tài)成員,Cpp,c++

? ? ? ? 事實(shí)上,類的靜態(tài)成員變量和靜態(tài)成員函數(shù),更像是普通的全局變量和全局函數(shù),

????????只是多了一層類作用域和訪問(wèn)控制限定符的約束,

????????相當(dāng)于? 具有成員訪問(wèn)屬性的全局變量和全局函數(shù)。

5? 類? 擴(kuò)充

? ? ? ? 空類對(duì)象的大小是1個(gè)字節(jié)。

? ? ? ? 類中不能包含? 本類對(duì)象? 作為? 普通成員變量;

? ? ? ? 類中可以包含? 本類對(duì)象? 作為? 靜態(tài)成員變量。

// class_add
#include <iostream>
using namespace std;
/*
class A { // 空類
};
int main( void ) {
    A a; // 空類對(duì)象占1個(gè)字節(jié)內(nèi)存(1個(gè)字節(jié)的垃圾數(shù)據(jù))
    A& ra = a;
    cout << "空類對(duì)象a的大小: " << sizeof(a) << endl;
    return 0;
}
*/


class A {
public:
    int m_i;
//  A m_a; // error
    static A m_sa; // ok
};
int main( void ) {
    A a; // 定義a(給a分配內(nèi)存空間)
    cout << "對(duì)象a的大小: " << sizeof(a) << endl;
    return 0;
}

6? 單例模式

? ? ? ? 要求:設(shè)計(jì)一個(gè)類,要求用戶在使用這個(gè)類時(shí)僅有一個(gè)實(shí)例(只能出現(xiàn)一個(gè)對(duì)象):

? ? ? ? class? Singleton {

? ? ? ? ? ? ? ? // 設(shè)計(jì)這個(gè)類

? ? ? ? };

? ? ? ? int? main(void) {

? ? ? ? ? ? ? ? // 用戶這里只能出現(xiàn)一個(gè)Singleton類對(duì)象,不能出現(xiàn)第二個(gè)

? ? ? ? ? ? ? ? return? 0;

? ? ? ? }

????????

? ? ? ? 實(shí)現(xiàn)方法:

? ? ? ? 1)將? 包括類的拷貝構(gòu)造函數(shù)在內(nèi)的所有構(gòu)造函數(shù) 私有化,防止user在類的外部創(chuàng)建對(duì)象。

? ? ? ? 2)唯一的對(duì)象由類的設(shè)計(jì)者來(lái)創(chuàng)建

? ? ? ? 3)提供公有靜態(tài)成員函數(shù)getInstance()使用戶可以獲取到唯一對(duì)象。

? ? ? ? 單例分類:

? ? ? ? 1)餓漢式:無(wú)論用不用,程序啟動(dòng)即創(chuàng)建? hungry.cpp (不推薦)

? ? ? ? 2)懶漢式:用的時(shí)候創(chuàng)建,不用了即銷毀? lazy.cpp? (推薦)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-770863.html

// hungry_singleton.cpp
// 單例模式--要求設(shè)計(jì)一個(gè)類型,用戶在使用這個(gè)類時(shí)只能出現(xiàn)一個(gè)對(duì)象
#include <iostream>
using namespace std;
// 餓漢式單例
class Singleton {
public://4        //5
    static Singleton& getInstance( ) {
        return s_instance;
    }
private:
    Singleton( ) {} // 1
    Singleton( const Singleton& that ) {} // 6
    static Singleton s_instance; // 2 唯一對(duì)象
};

Singleton Singleton::s_instance; // 3

// 以上代碼模擬類的設(shè)計(jì)者
// -----------------------
// 以下代碼模擬類的使用者
int main( void ) {
    Singleton& s1 = Singleton::getInstance( );
    Singleton& s2 = Singleton::getInstance( );
    Singleton& s3 = Singleton::getInstance( );
    cout << "&s1: " << &s1 << ", &s2: " << &s2 << ", &s3: " << &s3 << endl;
    return 0;
}
// lazy_singleton.cpp
// 單例模式:設(shè)計(jì)一個(gè)類,保證用戶在使用這個(gè)類時(shí),只能出現(xiàn)一個(gè)對(duì)象
#include <iostream>
using namespace std;
// 懶漢式單例:單例高級(jí)實(shí)現(xiàn)手法
class Singleton {
public:
    static Singleton& getInstance( ) {
        if( s_instance==NULL ) {
            s_instance = new Singleton; // 唯一的對(duì)象
            cout << "創(chuàng)建了唯一的對(duì)象" << endl;
        }
        ++s_counter;
        return *s_instance;
    }
    void releaseInstance( ) {
        if( --s_counter == 0 ) {
            delete s_instance;
            s_instance = NULL;
            cout << "銷毀了唯一的對(duì)象" << endl;
        }
    }
private:
    Singleton() {} 
    Singleton( const Singleton& that ) {} 
    static Singleton* s_instance; // 并不是唯一對(duì)象,僅僅是一個(gè)指針而已
    static int s_counter; // 計(jì)數(shù)功能
};

Singleton* Singleton::s_instance = NULL; // 程序剛剛時(shí),唯一的對(duì)象不存在 
int Singleton::s_counter = 0;

// 以上的代碼模擬類的設(shè)計(jì)者(例如:類庫(kù)、被人設(shè)計(jì)的類、自己的設(shè)計(jì)的類)
// -------------------------------------
// 以下的代碼模擬用戶(使用類的人)
int main( void ) {
    Singleton& s1 = Singleton::getInstance(); // 第一次調(diào)用getInstance函數(shù)時(shí),創(chuàng)建唯一的對(duì)象
    Singleton& s2 = Singleton::getInstance(); // 以后再調(diào)用getInstance函數(shù)時(shí),返回第一次調(diào)用時(shí)創(chuàng)建的對(duì)象
    Singleton& s3 = Singleton::getInstance(); // ...
    cout << "&s1: " << &s1 << ", &s2: " << &s2 << ", &s3: " << &s3 << endl;
    s1.releaseInstance( ); //
    s2.releaseInstance( ); // 
    s3.releaseInstance( ); // 最后一次調(diào)用releaseInstance才將對(duì)象銷毀
    return 0;
}

到了這里,關(guān)于cpp_07_類型轉(zhuǎn)換構(gòu)造_析構(gòu)函數(shù)_深拷貝_靜態(tài)成員的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包