C++基礎(chǔ)復(fù)習(xí)3

#include <iostream>
#include <string>


using namespace std;


/*
OOP的三大特性:封裝 繼承 多態(tài)


封裝:
    將靜態(tài)屬性和動(dòng)態(tài)行為封裝成一個(gè)整體
    屬性和行為加以權(quán)限控制:public private protect
        public:類外 類內(nèi)都可訪問
        private:類外不可訪問 類內(nèi)可以訪問
        protect:類外不可訪問 類內(nèi)可以訪問


    struct與class的區(qū)別:struct默認(rèn)權(quán)限是public class的默認(rèn)權(quán)限是private


構(gòu)造函數(shù):創(chuàng)建對(duì)象時(shí),為對(duì)象的成員屬性賦初始值,構(gòu)造函數(shù)由編譯器自行調(diào)用
    1.無返回值
    2.函數(shù)名與類名相同
    3.可以進(jìn)行函數(shù)重載,可以有參數(shù)
    4.每次創(chuàng)建調(diào)用時(shí)會(huì)自動(dòng)調(diào)用構(gòu)造函數(shù),且只會(huì)調(diào)用一次


構(gòu)造函數(shù)的分類:
    1.按參數(shù)分類:有參構(gòu)造函數(shù) 無參構(gòu)造函數(shù)
    2.按類型分類:普通構(gòu)造函數(shù) 拷貝構(gòu)造函數(shù)

構(gòu)造函數(shù)的調(diào)用方式: 括號(hào)法  顯示法  隱式轉(zhuǎn)換法




拷貝構(gòu)造函數(shù)調(diào)用時(shí)機(jī):
    1.用一個(gè)已有對(duì)象去初始化一個(gè)新的對(duì)象;
    2.值傳遞的方式給函數(shù)參數(shù)傳遞值;
    3.以值傳遞方式返回局部對(duì)象;




構(gòu)造函數(shù)的調(diào)用規(guī)則:
    1.默認(rèn)情況下,c++編譯器至少給一個(gè)類添加3個(gè)函數(shù):默認(rèn)構(gòu)造函數(shù)(無參數(shù)) 默認(rèn)析構(gòu)函數(shù)(無參數(shù)) 默認(rèn)拷貝構(gòu)造函數(shù)(對(duì)屬性進(jìn)行值拷貝)
    2.如果用戶定義了有參構(gòu)造函數(shù),c++不會(huì)再提供無參數(shù)的默認(rèn)構(gòu)造函數(shù),但是會(huì)提供默認(rèn)拷貝構(gòu)造函數(shù);
    3.如果用戶定義了拷貝構(gòu)造函數(shù),c++不會(huì)再提供其他構(gòu)造函數(shù);



析構(gòu)函數(shù):銷毀對(duì)象前,系統(tǒng)自動(dòng)調(diào)用清理內(nèi)存
    1.無返回值
    2.函數(shù)名與類名相同,且加上~
    3.析構(gòu)函數(shù)無參數(shù),不可以進(jìn)行函數(shù)重載
    4.對(duì)象銷毀前會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù)


// 淺拷貝與深拷貝
    // 淺拷貝:簡(jiǎn)單的賦值拷貝操作
    // 深拷貝:在heap上重新申請(qǐng)空間,進(jìn)行拷貝操作


// 類對(duì)象作為類成員:C++中類的成員可以是另一個(gè)類的對(duì)象,稱為對(duì)象成員
class A{

};

// 創(chuàng)建B對(duì)象時(shí),A和B的構(gòu)造函數(shù)與析構(gòu)函數(shù)誰(shuí)先誰(shuí)后呢?---先調(diào)用對(duì)象成員的構(gòu)造函數(shù),再調(diào)用本類的構(gòu)造函數(shù)
class B{
public:
    A a;
};



// 必須使用列表初始化的場(chǎng)景:
    注意:成員是按照他們?cè)陬愔谐霈F(xiàn)的順序進(jìn)行初始化的,而不是按照他們?cè)诔跏蓟斜沓霈F(xiàn)的順序初始化的
    1.常量成員,因?yàn)槌A恐荒艹跏蓟荒苜x值,所以必須放在初始化列表里面
    2.引用類型,引用必須在定義的時(shí)候初始化,并且不能重新賦值,所以也要寫在初始化列表里面
    3.沒有默認(rèn)構(gòu)造函數(shù)的類類型,因?yàn)槭褂贸跏蓟斜砜梢圆槐卣{(diào)用默認(rèn)構(gòu)造函數(shù)來初始化,而是直接調(diào)用拷貝構(gòu)造函數(shù)初始化。



// 靜態(tài)成員:在成員變量或成員函數(shù)前加上static關(guān)鍵字

靜態(tài)成員分為:
    靜態(tài)成員變量:
        1.所有對(duì)象共享同一份數(shù)據(jù)
        2.在編譯階段分配內(nèi)存
        3.類內(nèi)聲明,類外進(jìn)行初始化
    
    靜態(tài)成語(yǔ)函數(shù):
        1.所有對(duì)象共享同一個(gè)函數(shù)
        2.靜態(tài)成員函數(shù)只能訪問靜態(tài)成員變量

*/

const double PI = 3.14;

class Circle{
public:

    explicit Circle(int r):m_r(r) {}

    virtual ~Circle(){}

    double calculateZC() {
        return 2 * PI * m_r;
    }

private:
    int m_r;
};




class Student {
public:
    Student(string name, int age, int id):m_name(name) ,m_age(age), m_id(id) {}

    ~Student() {}

    void showStudentInfo() {
        cout << m_name << "  " << m_age << "  " << m_id << endl;
    }

    int m_aa;
private:
    string m_name;
    int m_age;
    int m_id;
};


// 構(gòu)造函數(shù)的分類及調(diào)用

class Person{
public:
    // 無參數(shù)的構(gòu)造函數(shù)
    Person() {
        cout << "not params\n";
    }

    // 有參的構(gòu)造函數(shù)
    Person(int age): m_age(age) {
        cout << "display params age\n";
    }


    // 拷貝構(gòu)造函數(shù)
    Person(const Person& p) {
        m_age = p.m_age;
        cout << "copy constructor has been called\n";
    }
    

    // 析構(gòu)函數(shù)
    ~Person(){
        cout << "deconstructor function\n";
    }


public:
    int m_age;
};


// 1.使用一個(gè)已初始化的對(duì)象來初始化一個(gè)新對(duì)象
void test01() {
    Person man(100);  // man是一個(gè)已經(jīng)創(chuàng)建好的對(duì)象
    Person newman(man); // 調(diào)用拷貝構(gòu)造函數(shù)
    Person newman2 = man;  // 調(diào)用拷貝構(gòu)造函數(shù)

    // Person newman3;   
    // newman3 = man;  // 不調(diào)用拷貝構(gòu)造函數(shù),只是普通賦值操作
}


// 2.以值傳遞的方式給函數(shù)傳遞參數(shù)
void doWork(Person p) {
    cout << "doWork: " << (int*)&p << endl;
}

void test02(){
    Person p;  // 無參構(gòu)造函數(shù)
    doWork(p);
}



// 3.以值傳遞的方式返回局部對(duì)象
Person doWork2() {
    Person p1;
    cout << "doWork2: " << (int*)&p1 << endl;
    return p1;
}

void test03() {
    Person p = doWork2();
    cout << "test03: " << (int*)&p << endl;
}


// 構(gòu)造函數(shù)的調(diào)用規(guī)則
void test04() {
    Person p1(18);
    // 如果不寫拷貝構(gòu)造函數(shù),編譯器會(huì)自動(dòng)添加拷貝構(gòu)造函數(shù),并且做淺拷貝操作
    Person p2(p1);
    cout << "p2 age is: " << p2.m_age << endl; 

}


// 淺拷貝與深拷貝
class Test {
public:
    // 默認(rèn)構(gòu)造函數(shù)
    Test() {
        cout << "默認(rèn)構(gòu)造函數(shù)\n";
    }

    // 用戶自定義構(gòu)造函數(shù)
    Test(int age, int height) {
        m_age = age;
        m_height = new int (height);
    }

    // 拷貝構(gòu)造函數(shù)
    Test(const Test& t) {
        cout << "Test copy structor\n";
        m_age = t.m_age;
        m_height = new int (*t.m_height);
    }

    // 析構(gòu)函數(shù)
    ~Test() {
        cout << "Test deconstructor function\n";
        if(m_height) {
            delete m_height;
        }
    }


    int m_age;
    int* m_height;
};


// 如果對(duì)象的屬性中有在heap上開辟的,一定要自己提供拷貝構(gòu)造函數(shù),不能使用默認(rèn)的拷貝構(gòu)造函數(shù)(淺拷貝)
void test05() {
    Test t1(18, 172);
    Test t2(t1);
    
    cout << "t1.age=" << t1.m_age << " *t1.m_height=" << *t1.m_height << endl;
    cout << "t2.age=" << t2.m_age << " *t2.m_height=" << *t2.m_height << endl;
}



// 類對(duì)象作為類成員
class Phone {
public:
    Phone(string name) {
        m_name = name;
        cout << "Phone constructor\n";
    }

    ~Phone() {
        cout << "Phone deconstructor\n";
    }

    string m_name;
};


class Curry {
public:
    Curry(string name, string pName): m_name(name), m_phone(pName) {
        cout << "Curry constructor\n";
    }

    ~Curry() {
        cout << "Curry deconstructor\n";
    }

    void playGame(){
        cout << m_name << " is using " << m_phone.m_name << " play games\n";
    }


    string m_name;
    Phone m_phone;  // 類中成員m_phone是Phone類的對(duì)象時(shí),此時(shí)m_phone稱為對(duì)象成員
};


void test06() {
    // 構(gòu)造順序:先調(diào)用對(duì)象成員的構(gòu)造函數(shù),再調(diào)用本類的構(gòu)造函數(shù);析構(gòu)對(duì)象時(shí)順序相反
    Curry cu("Curry", "xiaomi");
    cu.playGame();
}




// 靜態(tài)成員變量與靜態(tài)成員函數(shù)
    // 靜態(tài)成員變量
        // 1.所有對(duì)象共享同一份數(shù)據(jù)
        // 2.在編譯階段分配內(nèi)存
        // 3.類內(nèi)聲明,類外初始化

    // 靜態(tài)成員函數(shù)
        // 1.所有對(duì)象共享同一個(gè)函數(shù)
        // 2.靜態(tài)成員函數(shù)只能訪問靜態(tài)成員變量
class Hello{
public:
    static int m_H;  // 靜態(tài)成員變量

    int m_HO;  // 普通成員變量

    // 靜態(tài)成員函數(shù)
    static void func1(){
        cout << "func1 is called\n";
        m_H = 666;  // 靜態(tài)成員函數(shù)只能訪問靜態(tài)成員變量
        // m_HO = 721; 錯(cuò)誤,不可訪問非靜態(tài)成員變量
    }
private:
    static int m_L;

    static void func2() {
        cout << "func2 is called\n";
    }
};

// 靜態(tài)成員變量在類外初始化
int Hello::m_H = 100;
int Hello::m_L = 102;

// 靜態(tài)成員變量的訪問方式
void test07() {
    // 1.通過對(duì)象
    Hello h;
    h.m_H = 134;
    cout << "h.m_H =" << h.m_H << endl;

    Hello h1;
    h1.m_H = 999;
    // 共享同一份數(shù)據(jù)
    cout << "h.m_H =" << h.m_H << endl;
    cout << "h1.m_H =" << h1.m_H << endl;


    // 2.類名直接訪問
    cout << "h.m_H =" << Hello::m_H << endl;

    // 靜態(tài)成員函數(shù)的訪問方式
    // 1.通過對(duì)象
    Hello h2;
    h2.func1();

    cout << "h2.m_H =" << h2.m_H << endl;
    
    
    // 2.通過類名
    Hello::func1();
    // Hello::func2();  沒有訪問權(quán)限
    cout << "Hello::m_H =" << Hello::m_H << endl;
}

// C++中的對(duì)象模型和this指針
    // 1.在c++中,類內(nèi)的成員變量和成員函數(shù)分開存儲(chǔ)
    // 2.只有非靜態(tài)成員變量才屬于類的對(duì)象上

class Student1{
public:
    Student1() {
        m_id = 0;
    }

    // 普通成員函數(shù)也不占用對(duì)象空間,所有函數(shù)共用一個(gè)函數(shù)實(shí)例
    void func() {
        cout << "m_id = " << this->m_id << endl;
    }

    // 靜態(tài)成員函數(shù)不占用對(duì)象空間
    static void sfunc() {   
        cout << "TODO\n";
    }

private:
    // 非靜態(tài)成語(yǔ)變量占用對(duì)象空間
    double m_id;
    // 靜態(tài)成員變量不占用對(duì)象空間
    static int m_tel;
};


// this指針概念:
    // cpp中成員變量和成員函數(shù)是分開存儲(chǔ)的----->每個(gè)非靜態(tài)成員函數(shù)只會(huì)產(chǎn)生一份函數(shù)實(shí)例,即多個(gè)同類型的對(duì)象會(huì)共用一塊代碼
    // -------->同一塊非靜態(tài)成員函數(shù)代碼如何區(qū)分哪個(gè)對(duì)象調(diào)用自己的?
    // cpp通過特殊的對(duì)象指針this解決,this指針指向被調(diào)用的成員函數(shù)所屬的對(duì)象
    // this指針是隱含每一個(gè)非靜態(tài)成員函數(shù)內(nèi)的一種指針;
    // this指針用途:當(dāng)形參和成員變量同名時(shí),可以用this指針來區(qū)分;在類的非靜態(tài)成員函數(shù)中返回對(duì)象本身return *this
class Teacher{
public:
    Teacher(int age) {
        // 1.當(dāng)形參和成員變量同名時(shí),用this指針來區(qū)分
        this->age = age;
    }

    Teacher(const Teacher& t) {
        cout << "teacher copy constructor\n";
    }

    Teacher& TeacherAddTeacher(Teacher t){  // 會(huì)調(diào)用拷貝構(gòu)造函數(shù)
        this->age += t.age;
        // 2.返回對(duì)象本身
        return *this;
    }

    int age;
};

// 空指針訪問成員函數(shù)
// cpp中空指針也是可以訪問成員函數(shù)的,注意有沒有用到this指針,如果用到則需要加判斷來保證代碼的健壯性
class Player{
public:
    void showClassName(){
        cout << "Class Player\n";
    }

    void showPlayer(){
        if(this == nullptr) return;
        cout << mAge << endl;
    }
public:
    int mAge;
};


void test11() {
    Player* p = nullptr;
    p->showClassName();  // 空指針,可以調(diào)用成員函數(shù)
    p->showPlayer();  // 但是如果成員函數(shù)中用到了this指針,就不可以了
}

// const修飾成員函數(shù)
    // 常函數(shù):
        // 成員函數(shù)后加const后這個(gè)函數(shù)稱為常函數(shù)
        // 常函數(shù)內(nèi)部不可以修改成員屬性
        // 成員屬性聲明時(shí)加關(guān)鍵字mutable時(shí),在常函數(shù)內(nèi)部依然可以修改
    
    // 常對(duì)象:
        // 聲明對(duì)象前加const稱此對(duì)象是常對(duì)象
        // 常對(duì)象只能調(diào)用常函數(shù)

class Const{
public:
    Const(){
        m_A = 0;
        m_B = 0;
    }

    // this指針的本質(zhì)是一個(gè)指針常量,指針的指向不可以改變
    // 如果希望指針指向的值也不可以修改,需要聲明為常函數(shù)
    void showConst() const {

        // const修飾成員函數(shù),表示指針指向的內(nèi)存空間的數(shù)據(jù)不能被修改,除了mutable修飾的變量
        this->m_B = 100;
    }

    void MyFunc() const {
        // m_A = 100;
    }

public:
    int m_A;
    mutable int m_B;
};

void test22() {
    const Const cs;  // 常對(duì)象cs
    cout << cs.m_A << endl;
    // cs.mA = 100; 常對(duì)象不能修改成員變量的值,但可以訪問
    
    cs.m_B = 1000;
    cs.MyFunc(); // 常對(duì)象只能訪問常成員函數(shù)

}



int main() {
    
    // Circle c(2); 顯式

    // Circle c = 10;  隱式

    Circle c(10);

    cout << "ZC is: " << c.calculateZC() << endl;\


    Student stu("zhangsan", 18, 1120001);
    stu.showStudentInfo();

    // stu.m_name; 類外不可以訪問
    // stu.m_aa;  類外可以訪問



    // 構(gòu)造函數(shù)的分類及調(diào)用

    Person p; // 調(diào)用無參構(gòu)造函數(shù)
    Person p1(10);  // 括號(hào)法  顯示法
    Person p2 = 20;  // 隱式轉(zhuǎn)換法

    Person p3 = Person(18);

    Person p4 = p2;  // 調(diào)用拷貝構(gòu)造函數(shù)

    test02();
    test03();

    cout << "--------test04---------\n";
    test04();

    cout << "--------Test---------\n";
    test05();

    cout << "--------test06---------\n";
    test06();


    cout << "--------test07---------\n";
    test07();

    cout << "--------test08---------\n";
    cout << "sizeof(Student1) = " << sizeof(Student1) << endl;

    cout << "--------test09---------\n";
    Student1 s1;
    s1.func();

    cout << "--------test10---------\n";
    Teacher t1(24);
    cout << "t1.age = " << t1.age << endl;

    cout << "-----split line---------\n";
    Teacher t2(35);
    t2.TeacherAddTeacher(t1).TeacherAddTeacher(t1).TeacherAddTeacher(t1);
    cout << "t2.age = " << t2.age << endl;

    cout << "--------test11---------\n";
    test11();
    cout << "--------test22---------\n";
    test22();

    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容