• C++面向对象模型初探


    4.4.1 成员变量和函数的存储

    c语言中,“分开来声明的,也就是说,语言本身并没有支持“数据”和“函数”之间的关联性我们把这种程序方法称为“程序性的”,由一组“分布在各个以功能为导航的函数中”的算法驱动,它们处理的是共同的外部数据。

    c++实现了“封装”,那么数据(成员属性)和操作(成员函数)是什么样的呢?

    “数据”和“处理数据的操作(函数)”是分开存储的。

    n c++中的非静态数据成员直接内含在类对象中,就像c struct一样。

    成员函数(member function)虽然内含在class声明之内,却不出现在对象中。

    每一个非内联成员函数(non-inline member function)只会诞生一份函数实例.

    class MyClass01{
    public:
        int mA;
    };
    
    class MyClass02{
    public:
        int mA;
        static int sB;
    };
    
    class MyClass03{
    public:
        void printMyClass(){
            cout << "hello world!" << endl;
        }
    public:
        int mA;
        static int sB;
    };
    
    class MyClass04{
    public:
        void printMyClass(){
            cout << "hello world!" << endl;
        }
        static void ShowMyClass(){
            cout << "hello world!" << endl;
        }
    public:
        int mA;
        static int sB;
    };
    
    int main(){
    
        MyClass01 mclass01;
        MyClass02 mclass02;
        MyClass03 mclass03;
        MyClass04 mclass04;
    
        cout << "MyClass01:" << sizeof(mclass01) << endl; //4
        //静态数据成员并不保存在类对象中
        cout << "MyClass02:" << sizeof(mclass02) << endl; //4
        //非静态成员函数不保存在类对象中
        cout << "MyClass03:" << sizeof(mclass03) << endl; //4
        //静态成员函数也不保存在类对象中
        cout << "MyClass04:" << sizeof(mclass04) << endl; //4
    
        return EXIT_SUCCESS;
    }

    通过上面的案例,我们可以的得出:C++类对象中的变量和函数是分开存储。

    4.4.2 this指针

    4.4.2.1 this指针工作原理

    通过上例我们知道,c++的数据和操作也是分开存储,并且每一个非内联成员函数(non-inline member function)只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码

    那么问题是:这一块代码是如何区分那个对象调用自己的呢?

    c++通过提供特殊的对象指针,this指针,解决上述问题。This指针指向被调用的成员函数所属的对象。

      c++规定,this指针是隐含在对象成员函数内的一种指针。当一个对象被创建后,它的每一个成员函数都含有一个系统自动生成的隐含指针this,用以保存这个对象的地址,也就是说虽然我们没有写上this指针,编译器在编译的时候也是会加上的。因此this也称为“指向本对象的指针”,this指针并不是对象的一部分,不会影响sizeof(对象)的结果。

       this指针是C++实现封装的一种机制,它将对象和该对象调用的成员函数连接在一起,在外部看来,每一个对象都拥有自己的函数成员。一般情况下,并不写this,而是让系统进行默认设置。

          this指针永远指向当前对象。

    成员函数通过this指针即可知道操作的是那个对象的数据。This指针是一种隐含指针,它隐含于每个类的非静态成员函数中This指针无需定义,直接使用即可。

    注意:静态成员函数内部没有this指针,静态成员函数不能操作非静态成员变量。

                 c++编译器对普通成员函数的内部处理

    4.4.2.2 this指针的使用

    当形参和成员变量同名时,可用this指针来区分

    在类的非静态成员函数中返回对象本身,可使用return *this.

    class Person{
    public:
        //1. 当形参名和成员变量名一样时,this指针可用来区分
        Person(string name,int age){
            //name = name;
            //age = age; //输出错误
            this->name = name;
            this->age = age;
        }
        //2. 返回对象本身的引用
        //重载赋值操作符
        //其实也是两个参数,其中隐藏了一个this指针
        Person PersonPlusPerson(Person& person){
            string newname = this->name + person.name;
            int newage = this->age + person.age;
            Person newperson(newname, newage);
            return newperson;
        }
        void ShowPerson(){
            cout << "Name:" << name << " Age:" << age << endl;
        }
    public:
        string name;
        int age;
    };
    
    //3. 成员函数和全局函数(Perosn对象相加)
    Person PersonPlusPerson(Person& p1,Person& p2){
        string newname = p1.name + p2.name;
        int newage = p1.age + p2.age;
        Person newperson(newname,newage);
        return newperson;
    }
    
    int main(){
    
        Person person("John",100);
        person.ShowPerson();
    
        cout << "---------" << endl;
        Person person1("John",20);
        Person person2("001", 10);
        //1.全局函数实现两个对象相加
        Person person3 = PersonPlusPerson(person1, person2);
        person1.ShowPerson();
        person2.ShowPerson();
        person3.ShowPerson();
        //2. 成员函数实现两个对象相加
        Person person4 = person1.PersonPlusPerson(person2);
        person4.ShowPerson();
    
        system("pause");
        return EXIT_SUCCESS;
    }

    4.4.2.3 const修饰成员函数

    const修饰的成员函数时,const修饰this指针指向的内存区域,成员函数体内不可以修改本类中的任何普通成员变量,

    当成员变量类型符前用mutable修饰时例外。

    //const修饰成员函数
    class Person{
    public:
        Person(){
            this->mAge = 0;
            this->mID = 0;
        }
        //在函数括号后面加上const,修饰成员变量不可修改,除了mutable变量
        void sonmeOperate() const{
            //this->mAge = 200; //mAge不可修改
            this->mID = 10;
        }
        void ShowPerson(){
            cout << "ID:" << mID << " mAge:" << mAge << endl;
        }
    private:
        int mAge;
        mutable int mID;
    };
    
    int main(){
    
        Person person;
        person.sonmeOperate();
        person.ShowPerson();
    
        system("pause");
        return EXIT_SUCCESS;
    }

    4.4.2.4 const修饰对象(常对象)

    常对象只能调用const的成员函数

    常对象可访问 const 或非 const 数据成员,不能修改,除非成员用mutable修饰

    class Person{
    public:
        Person(){
            this->mAge = 0;
            this->mID = 0;
        }
        void ChangePerson() const{
            mAge = 100;
            mID = 100;
        }
        void ShowPerson(){
            this->mAge = 1000;
            cout << "ID:" << this->mID << " Age:" << this->mAge << endl;
        }
    
    public:
        int mAge;
        mutable int mID;
    };
    
    void test(){    
        const Person person;
        //1. 可访问数据成员
        cout << "Age:" << person.mAge << endl;
        //person.mAge = 300; //不可修改
        person.mID = 1001; //但是可以修改mutable修饰的成员变量
        //2. 只能访问const修饰的函数
        //person.ShowPerson();
        person.ChangePerson();
    }
  • 相关阅读:
    luogu3242 接水果 (整体二分+树状数组)
    [BZOJ3449] [Usaco2014 Feb]Secret Code
    [BZOJ2821] 作诗(Poetize)
    [BZOJ2434] [Noi2011]阿狸的打字机
    [BZOJ1212] [HNOI2004]L语言
    [JZOJ100026]【NOIP2017提高A组模拟7.7】图
    [BZOJ2467] [中山市选2010]生成树
    [Luogu3868] [TJOI2009]猜数字
    [POJ1006] Biorhythms
    [BZOJ2733] [HNOI2012]永无乡
  • 原文地址:https://www.cnblogs.com/mmc9527/p/10430168.html
Copyright © 2020-2023  润新知