欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

初識(shí)C++02:類和對象

類和對象

創(chuàng)建方法

第一種式直接聲明:

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、重慶小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了梅州免費(fèi)建站歡迎大家使用!

class Student {
private:
    string name;
public:
    Student(string name) {
        this->name = name;
    }
}
//聲明:
Student lu;//不帶初始化
//帶初始化;
Student lu(huang);
Student lu = Student(huang);
//訪問方式
lu.name;

這樣的聲明方式,是將對象在棧上創(chuàng)建,棧內(nèi)存自動(dòng)管理,在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束后在將這些局部變量的內(nèi)存空間回收。在棧上分配內(nèi)存空間效率很高,但是分配的內(nèi)存容量有限。

第二種使用對象指針聲明

Student *plu = new Student;//不帶初始化;
Student *plu = new Student(huang);//帶初始化;
//訪問方式
plu->name;

這樣聲明,是將對象在堆中創(chuàng)建,堆內(nèi)存代碼人員管理,new和delete配對使用。使用 new 在堆上創(chuàng)建出來的對象是匿名的,沒法直接使用,必須要用一個(gè)指針指向它,再借助指針來訪問它的成員變量或成員函數(shù)。

函數(shù)聲明

成員函數(shù)必須先在類體中作原型聲明,然后在類外定義,也就是說類體的位置應(yīng)在函數(shù)定義之前。因?yàn)轭愺w內(nèi)定義的函數(shù)默認(rèn)是內(nèi)聯(lián)函數(shù),一般用內(nèi)聯(lián)函數(shù)的時(shí)候才會(huì)在類內(nèi)部實(shí)現(xiàn);例子:

class Student {
private:
    string name;
    int age;
public:
    //函數(shù)聲明
    Student(string name, int age);
}
//函數(shù)定義
Student::Student(string name, int age) {
    this->name = name;
    this->age = age;
}

類成員的訪問權(quán)限以及封裝

在類的內(nèi)部(定義類的代碼內(nèi)部),無論成員被聲明為 public、protected 還是 private,都是可以互相訪問的,沒有訪問權(quán)限的限制。

在類的外部(定義類的代碼之外),只能通過對象訪問成員,并且通過對象只能訪問 public 屬性的成員,不能訪問 private、protected 屬性的成員。

成員變量大都以m_開頭,這是約定成俗的寫法,易區(qū)分。

建議在開發(fā)中不需要暴暴露出來的屬性和方法都寫成private;

給成員變量賦值的函數(shù)通常稱為 set XXX函數(shù),讀取成員變量的值的函數(shù)通常稱為 get XXX函數(shù),XXX表示變量名;類中的不寫private這些關(guān)鍵詞默認(rèn)是private;

class Student {
private:
    string m_name;
public:
    void setname(string name);
    void getname;
}
void Student::setname(string name) {
    m_name = name;//這里可以直接用m_name;
}
.....

對象內(nèi)存模型和函數(shù)編譯原理及實(shí)現(xiàn)

編譯器會(huì)將成員變量和成員函數(shù)分開存儲(chǔ):分別為每個(gè)對象的成員變量分配內(nèi)存,但是所有對象都共享同一段函數(shù)代碼,節(jié)省空間,sizeof一個(gè)對象大小就是全部成員變量的總和大小;

C++和C語言的編譯方式不同。C語言中的函數(shù)在編譯時(shí)名字不變,或者只是簡單的加一個(gè)下劃線_(不同的編譯器有不同的實(shí)現(xiàn)),c++是通過一種特殊的算法來實(shí)現(xiàn)的,對函數(shù)重命名(這個(gè)過程叫字編碼(Name Mangling));下圖是一個(gè)編譯器重命名的方式,?方法@類名.....

從上圖可以看出,成員函數(shù)最終被編譯成與對象無關(guān)的全局函數(shù),如果函數(shù)體中沒有成員變量,不用對函數(shù)做任何處理,直接調(diào)用即可。

如果有成員變量(它的作用域不是全局的),C++規(guī)定,編譯成員函數(shù)時(shí)要額外添加一個(gè)參數(shù),把當(dāng)前對象的指針傳遞進(jìn)去,通過指針來訪問成員變量(實(shí)際上傳遞的就是this指針

void Demo::display(){
    cout<<a<<endl;
}

會(huì)編譯為類似:

void new_function_name(Demo * const p){//const表示指針不能被修改;
    //通過指針p來訪問a、b
    cout<<p->a<<endl;
}

這樣通過傳遞對象指針就完成了成員函數(shù)和成員變量的關(guān)聯(lián)。這與我們從表明上看到的剛好相反,通過對象調(diào)用成員函數(shù)時(shí),不是通過對象找函數(shù),而是通過函數(shù)找對象。

構(gòu)造函數(shù)

構(gòu)造函數(shù)的調(diào)用是強(qiáng)制性的,一旦在類中定義了構(gòu)造函數(shù),那么創(chuàng)建對象時(shí)就一定要調(diào)用,不調(diào)用是錯(cuò)誤的。如果有多個(gè)重載的構(gòu)造函數(shù),那么創(chuàng)建對象時(shí)提供的實(shí)參必須和其中的一個(gè)構(gòu)造函數(shù)匹配;反過來說,創(chuàng)建對象時(shí)只有一個(gè)構(gòu)造函數(shù)會(huì)被調(diào)用;

一個(gè)類必須有構(gòu)造函數(shù),要么用戶自己定義,要么編譯器自動(dòng)生成。一旦用戶自己定義了構(gòu)造函數(shù),不管有幾個(gè),也不管形參如何,編譯器都不再自動(dòng)生成。

構(gòu)造函數(shù)定義由兩種寫法:正常函數(shù)寫法和使用構(gòu)造函數(shù)初始化列表

//第一種
Student::Student(char *name, int age){
    m_name = name;
    m_age = age;
}
//第二種
Student::Student(char *name, int age): m_name(name), m_age(age){}

注意????第二種:成員變量的初始化順序與初始化列表中列出的變量的順序無關(guān),它只與成員變量在類中聲明的順序有關(guān);如:

class Demo{
private:
    int m_a;
    int m_b;
public:
    Demo(int b);
    void show();
};

Demo::Demo(int b): m_b(b), m_a(m_b){
    m_a = m_b;
    m_b = b;
}
//錯(cuò)誤,給 m_a 賦值時(shí),m_b 還未被初始化,它的值是不確定的,所以輸出的 m_a 的值是一個(gè)奇怪的數(shù)字;給 m_a 賦值完成后才給 m_b 賦值,此時(shí) m_b 的值才是 值b。
//obj 在棧上分配內(nèi)存,成員變量的初始值是不確定的。

使用構(gòu)造函數(shù)初始化列表并沒有效率上的優(yōu)勢,但是書寫方便,而且,初始化 const 成員變量的唯一方法就是使用初始化列表,原因:為什么要用初始化列表

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

析構(gòu)函數(shù)(Destructor)也是一種特殊的成員函數(shù),沒有返回值,不需要程序員顯式調(diào)用(程序員也沒法顯式調(diào)用),而是在銷毀對象時(shí)自動(dòng)執(zhí)行。

class VLA{
public:
    VLA(int len);  //構(gòu)造函數(shù)
    ~VLA();  //析構(gòu)函數(shù)
private:
    const int m_len;  //數(shù)組長度
    int *m_arr; //數(shù)組指針
    int *m_p;  //指向數(shù)組第i個(gè)元素的指針
};
VLA::VLA(int len): m_len(len){  //使用初始化列表來給 m_len 賦值
    if(len > 0){ m_arr = new int[len];  /*分配內(nèi)存*/ }
    else{ m_arr = NULL; }
}
VLA::~VLA(){
    delete[] m_arr;  //釋放內(nèi)存
}

通過直接用類聲明的對象在棧中,出了作用域(比如說函數(shù)return了),就會(huì)調(diào)用析構(gòu)函數(shù);在全局建的對象在.data區(qū),程序結(jié)束后才釋放; 注意?????????♂?:兩中方法調(diào)用析構(gòu)函數(shù)的順序都是先生成的后析構(gòu),后生成的先析構(gòu);

new 創(chuàng)建的對象位于堆區(qū),通過 delete 刪除時(shí)才會(huì)調(diào)用析構(gòu)函數(shù),例如在main函數(shù)中new對象然后delete對象;如果聲明了變量在堆中,不通過析構(gòu)函數(shù)釋放內(nèi)存,即使外面delete了,也只是刪除了指針,里面的空間還是被占用著,沒有被釋放掉,如上面的int[len];

此處補(bǔ)充指針知識(shí):

int a = 10;
int* p = &a;//p是指針,這個(gè)*表示是int的指針類型;
此時(shí) *p = 10//這里的*說明是這個(gè)指針指向的對象,與上面*大大不同;而p只是以一個(gè)地址

成員對象和封閉類

一個(gè)類的成員變量如果是另一個(gè)類的對象,就稱之為“成員對象”。包含成員對象的類叫封閉類。

創(chuàng)建封閉類的對象時(shí),它包含的成員對象也需要被創(chuàng)建,這就會(huì)引發(fā)成員對象構(gòu)造函數(shù)的調(diào)用,對于沒有默認(rèn)構(gòu)造函數(shù)的成員對象,必須要使用封閉類構(gòu)造函數(shù)的初始化列表?。。?/strong>

類名::構(gòu)造函數(shù)名(參數(shù)表): 成員變量1(參數(shù)表), 成員變量2(參數(shù)表), ...
{
//TODO:
}

一定要用初始化列表的四種情況

初始化時(shí):封閉類對象生成時(shí),先執(zhí)行所有成員對象的構(gòu)造函數(shù),然后才執(zhí)行封閉類自己的構(gòu)造函數(shù);

消亡時(shí):先執(zhí)行封閉類的析構(gòu)函數(shù),然后再執(zhí)行成員對象的析構(gòu)函數(shù),剛剛好和創(chuàng)建相反。

this指針、static關(guān)鍵字

C++ 中的一個(gè)關(guān)鍵字,也是一個(gè) const 指針, 所以要用->來訪問成員變量或成員函數(shù)。它指向當(dāng)前對象,通過它可以訪問當(dāng)前對象的所有成員。

this的本質(zhì):this 實(shí)際上是成員函數(shù)的一個(gè)形參,在調(diào)用成員函數(shù)時(shí)將對象的地址作為實(shí)參傳遞給 this。不過 this 這個(gè)形參是隱式的,它并不出現(xiàn)在代碼中,而是在編譯階段由編譯器默默地將它添加到參數(shù)列表中。

上述中函數(shù)編譯原理:成員函數(shù)最終被編譯成與對象無關(guān)的普通函數(shù),除了成員變量,會(huì)丟失所有信息,所以編譯時(shí)要在成員函數(shù)中添加一個(gè)額外的參數(shù),把當(dāng)前對象的首地址傳入,以此來關(guān)聯(lián)成員函數(shù)和成員變量。這個(gè)額外的參數(shù),實(shí)際上就是 this,它是成員函數(shù)和成員變量關(guān)聯(lián)的橋梁。

static修飾成員變量:

  • 一個(gè)類中可以有一個(gè)或多個(gè)靜態(tài)成員變量,所有的對象都共享這些靜態(tài)成員變量,都可以引用它。

  • static 成員變量和普通 static 變量一樣,都在內(nèi)存分區(qū)中的全局?jǐn)?shù)據(jù)區(qū)分配內(nèi)存,到程序結(jié)束時(shí)才釋放。這就意味著,static 成員變量不隨對象的創(chuàng)建而分配內(nèi)存,也不隨對象的銷毀而釋放內(nèi)存。而普通成員變量在對象創(chuàng)建時(shí)分配內(nèi)存,在對象銷毀時(shí)釋放內(nèi)存。

  • 靜態(tài)成員變量必須初始化,而且只能在類體外進(jìn)行。例如:int Student::m_total = 10;初始化時(shí)可以賦初值,也可以不賦值。如果不賦值,那么會(huì)被默認(rèn)初始化為 0。全局?jǐn)?shù)據(jù)區(qū)的變量都有默認(rèn)的初始值 0,而動(dòng)態(tài)數(shù)據(jù)區(qū)(堆區(qū)、棧區(qū))變量的默認(rèn)值是不確定的,一般認(rèn)為是垃圾值。

  • 靜態(tài)成員變量既可以通過對象名訪問,也可以通過類名訪問,但要遵循 private、protected 和 public 關(guān)鍵字的訪問權(quán)限限制。當(dāng)通過對象名訪問時(shí),對于不同的對象,訪問的是同一份內(nèi)存。

static修飾成員函數(shù):

靜態(tài)成員函數(shù)與普通成員函數(shù)的根本區(qū)別在于:普通成員函數(shù)有 this 指針,可以訪問類中的任意成員;而靜態(tài)成員函數(shù)沒有 this 指針,只能訪問靜態(tài)成員(包括靜態(tài)成員變量和靜態(tài)成員函數(shù))

原因:編譯器在編譯一個(gè)普通成員函數(shù)時(shí),會(huì)隱式地增加一個(gè)形參 this,并把當(dāng)前對象的地址賦值給 this,所以普通成員函數(shù)只能在創(chuàng)建對象后通過對象來調(diào)用,因?yàn)樗枰?dāng)前對象的地址。而靜態(tài)成員函數(shù)可以通過類來直接調(diào)用編譯器不會(huì)為它增加形參 this,它不需要當(dāng)前對象的地址,所以不管有沒有創(chuàng)建對象,都可以調(diào)用靜態(tài)成員函數(shù),所以靜態(tài)成員函數(shù)也無法訪問普通成員變量,只能訪問靜態(tài)成員(在全局)。

const 成員變量/成員函數(shù)(常成員函數(shù))/對象

const成員變量:加上 const 關(guān)鍵字。初始化 const 成員變量只有一種方法,就是通過構(gòu)造函數(shù)的初始化列表

const成員函數(shù): const 成員函數(shù)可以使用類中的所有成員變量,但是不能修改它們的值,這種措施主要還是為了保護(hù)數(shù)據(jù)而設(shè)置的。一般類中的get函數(shù)都設(shè)置為常成員函數(shù),只讀不給改;

  • 函數(shù)開頭的 const 用來修飾函數(shù)的返回值,表示返回值是 const 類型,也就是不能被修改,例如const char * getname()。

  • 函數(shù)頭部的結(jié)尾加上 const 表示常成員函數(shù),這種函數(shù)只能讀取成員變量的值,而不能修改成員變量的值,例如char * getname() const

    class Student {
    public:
        Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score) {}//方法實(shí)現(xiàn)都不寫;
        char *getname() const;
    prviate:
        char *m_name;
        int m_age;
        float m_score; 
    };
    char* Student::getname() const {
        return m_name;
    }//方法實(shí)現(xiàn)都不寫;
    

const對象: const 也可以用來修飾對象,稱為常對象。一旦將對象定義為常對象之后,就只能調(diào)用類的 const 成員(包括 const 成員變量和 const 成員函數(shù))了,因?yàn)榉?const 成員可能會(huì)修改對象的數(shù)據(jù)(編譯器也會(huì)這樣假設(shè)),C++禁止這樣做。

友元函數(shù)和友元類

借助友元(friend),可以使得其他類中的成員函數(shù)以及全局范圍內(nèi)的函數(shù)訪問當(dāng)前類的 private 成員。在當(dāng)前類以外定義的、不屬于當(dāng)前類的函數(shù)也可以在類中聲明,但要在前面加 friend 關(guān)鍵字,這樣就構(gòu)成了友元函數(shù)。友元函數(shù)可以是不屬于任何類的 非成員函數(shù),也可以是其他類的成員函數(shù)。

  • 將非成員函數(shù)聲明為友元函數(shù)
class Student{
public:
    Student(char *name, int age, float score);
public:
    friend void show(Student *pstu);  //將show()聲明為友元函數(shù)
private:
    char *m_name;
    int m_age;
    float m_score;
};
//非成員函數(shù)
void show(Student *pstu){//屬于全局函數(shù),通過參數(shù)傳遞對象,可以訪問private成員變量
    cout<<pstu->m_name<<"的年齡是 "<<pstu->m_age<<",成績是 "<<pstu->m_score<<endl;
}
  • 將其他類的成員函數(shù)聲明為友元函數(shù),該成員函數(shù)提供給一個(gè)類用
class Address;  //一定要提前聲明Address類
//聲明Student類
class Student{
public:
    Student(char *name, int age, float score);
public:
    void show(Address *addr);//要使用的類,前面有聲明address所以不會(huì)報(bào)錯(cuò)?。。。。。。。。。。。。。。。?!
private:
    char *m_name;
    int m_age;
    float m_score;
};
//聲明Address類
class Address{
private:
    char *m_province;  //省份
    char *m_city;  //城市
    char *m_district;  //區(qū)(市區(qū))
public:
    Address(char *province, char *city, char *district);
    //將Student類中的成員函數(shù)show()聲明為友元函數(shù)
    friend void Student::show(Address *addr);//!?。。。。。。。。。。。。。。。。。?};
//實(shí)現(xiàn)Student類
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(Address *addr){
    cout<<m_name<<"的年齡是 "<<m_age<<",成績是 "<<m_score<<endl;
    cout<<"家庭住址:"<<addr->m_province<<"省"<<addr->m_city<<"市"<<addr->m_district<<"區(qū)"<<endl;
}

友元類:

將類 B 聲明為類 A 的友元類,那么類 B 中的所有成員函數(shù)都是類 A 的友元函數(shù),可以訪問類 A 的所有成員,包括 public、protected、private 屬性的

class Address;  //提前聲明Address類
//聲明Student類
class Student{
public:
    Student(char *name, int age, float score);
public:
    void show(Address *addr);
private:
    char *m_name;
    int m_age;
    float m_score;
};
//聲明Address類
class Address{
public:
    Address(char *province, char *city, char *district);
public:
    //將Student類聲明為Address類的友元類
    friend class Student;
private:
    char *m_province;  //省份
    char *m_city;  //城市
    char *m_district;  //區(qū)(市區(qū))
};
//實(shí)現(xiàn)Student類
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(Address *addr){
    cout<<m_name<<"的年齡是 "<<m_age<<",成績是 "<<m_score<<endl;
    cout<<"家庭住址:"<<addr->m_province<<"省"<<addr->m_city<<"市"<<addr->m_district<<"區(qū)"<<endl;
}
//實(shí)現(xiàn)Address類
Address::Address(char *province, char *city, char *district){
    m_province = province;
    m_city = city;
    m_district = district;
}
  • 友元的關(guān)系是單向的而不是雙向的。如果聲明了類 B 是類 A 的友元類,不等于類 A 是類 B 的友元類,類 A 中的成員函數(shù)不能訪問類 B 中的 private 成員。
  • 友元的關(guān)系不能傳遞。如果類 B 是類 A 的友元類,類 C 是類 B 的友元類,不等于類 C 是類 A 的友元類。
  • 除非有必要,一般不建議把整個(gè)類聲明為友元類,而只將某些成員函數(shù)聲明為友元函數(shù),這樣更安全一些。

ps: 其實(shí)類也是一種作用域 , 普通的成員只能通過對象(可以是對象本身,也可以是對象指針或?qū)ο笠茫﹣碓L問,靜態(tài)成員既可以通過對象訪問,又可以通過類訪問,而 typedef 定義的類型只能通過類來訪問

struct和class的區(qū)別

C++中,struct 類似于 class,既可以包含成員變量,又可以包含成員函數(shù)。

C++中的 struct 和 class 基本是通用的,唯有幾個(gè)細(xì)節(jié)不同:

  • 使用 class 時(shí),類中的成員默認(rèn)都是 private 屬性的;而使用 struct 時(shí),結(jié)構(gòu)體中的成員默認(rèn)都是 public 屬性的。
  • class 繼承默認(rèn)是 private 繼承,而 struct 繼承默認(rèn)是 public 繼承(到繼承會(huì)講)。
  • class 可以使用模板,而 struct 不能(到模板會(huì)講)。

建議使用 class 來定義類,而使用 struct 來定義結(jié)構(gòu)體,這樣做語義更加明確

分享標(biāo)題:初識(shí)C++02:類和對象
文章源于:http://chinadenli.net/article18/dsoipgp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)關(guān)鍵詞優(yōu)化、用戶體驗(yàn)網(wǎng)站營銷、網(wǎng)站導(dǎo)航域名注冊

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)