C++对象模型和this指针学习案例

1.成员变量和成员函数分开存储

#include <iostream>
using namespace std;

// 空类的对象 size 为1
class NullClass{
     
};

class Person{
    int m_A;  // 非静态成员变量 属于类的对象上
};

class All{
    int m_A;            // 非静态成员变量 属于类的对象上
    static int m_B;     // 静态成员变量 不属于类的对象上
    void func(){}          // 非静态成员函数 不属于类的对象上
    static void func2(){}  // 静态成员函数 不属于类的对象上

};

int All::m_B = 0;

void test01(){
    NullClass p;
    cout << "size of 空类对象 p = "<< sizeof(p) << endl;

    Person q;
    cout << "size of 包含非静态成员变量的对象 q = "<< sizeof(q) << endl;

    All a;
    cout << "size of 包含所有的对象 a = "<< sizeof(a) << endl;

}

int main(){
    test01();
}

2.this指针概念

#include <iostream>
using namespace std;

// this指针
// 用来指向被调用的成员函数所属的对象

// 用途1: 解决形参和属性名冲突
// 用途2: 在类的非静态成员函数中返回对象本身,可使用return *this

class Person{
public:
    Person(int age){
        // age = age; // 形参和属性名冲突
        this->age = age; // 1,使用this指针解决冲突
    }

    // 返回类型时Person时, 是以值的方式返回,会调用拷贝构造函数,返回一个新的p2
    Person FalsePersonAddAge(Person p){
        this->age += p.age;
        return *this;
    }
    
    // 返回类型时Person&时, 是以引用的方式返回,返回的是p2本身
    Person& TruePersonAddAge(Person p){
        this->age += p.age;
        return *this;   // 2.在类的非静态成员函数中返回对象本身,可使用return *this
    }
    
    int age;
};


void test01(){
    Person p1(10);
    cout <<  "p1 age = " << p1.age << endl;

    Person p2(10);
    p2.FalsePersonAddAge(p1).FalsePersonAddAge(p1).FalsePersonAddAge(p1); // 链式编程思想
    cout << "p2 age = " << p2.age << endl;   // 20

    Person p3(10);
    p3.FalsePersonAddAge(p1).FalsePersonAddAge(p1).FalsePersonAddAge(p1); // 链式编程思想
    cout << "p3 age = " << p3.age << endl;   // 40

}

int main(){
    test01();
}

3.空指针访问成员函数

#include <iostream>
using namespace std;

// C++中 空指针也可以调用成员函数,但要注意成员函数中有没有用到this指针
// 如果用到了,需要在成员函数中加以判断,保证代码的鲁棒性

class Person{
public:
    void showClassName(){
        cout << "Person 类" << endl;
    }
    void showPersonAge(){

        // 报错原因是因为传入指针为NULL,因此要加上判断, 这样就不会报错了
        if(this != NULL){
            cout << "age = " << m_age << endl; // 编译器默认会加上 this->m_age
        }   
        
    }

    int m_age;

};

void test01(){

    // 空指针, 类型为Person *
    Person * p = NULL;

    p->showClassName();

    p->showPersonAge(); 

}

int main(){
    test01();
}

4.const修饰成员函数

#include <iostream>
using namespace std;

// 常(成员)函数
// 1.成员函数后加const 表示这个函数为常成员函数
// 2.常成员函数内不可以修改成员属性
// 3.但是如果成员属性声名时加上mutable关键字,在常成员函数中依然可以修改

// 常对象
// 1. 声名对象时加const修饰 表示这个对象为常对象
// 2. 常对象只能调用常成员函数

class Person{
public:
    void showPerson() const  // 常成员函数
    {
        // m_A = 100;  
        // 报错,不允许修改 相当于this—>m_A = 100
        // this指针本质是指针常量,指向不可以修改,但指向的值可以修改,相当于Person * const this
        // 成员函数加上const,修饰的是this指针的指向,相当于 const Person * const this
    }

    int m_A;
};

class Person2{
public:
    void showPerson2() const   // 常成员函数
    {
        m_A = 100;  // 不报错,允许修改
        cout << "m_A = " << this->m_A << endl;
    }
    void func(){

    }

    mutable int m_A; // 加上mutable关键字
};

void test01(){
    const Person2 p; // 常对象
    p.m_A = 0;
    p.showPerson2();
    // p.func(); // 报错,常对象不能调用除常函数外的函数
    // 因为func()可以对属性进行修改,如果常对象能调用除常函数外的函数,那么就会间接修改属性,这样是不行的
}

int main(){
    test01();
}
上一篇:下载网易云和酷我歌曲


下一篇:集合的理解和好处