C++ —— 类和对象(二)

this指针

一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。

this指针引出

每一个非静态成员函数只会诞生一份函数实例, 也就是说多个同类型的对象会共用一块代码。
那么问题是:这一块代码是如何区分那个对象调用自己的呢?
C++通过提供特殊的对象指针,this指针, 解决上述问题。this指针指向被调用的成员函数所属的对象

this指针的特性

  1. this指针的类型:类类型* const。
  2. 只能在“成员函数”的内部使用。
  3. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
  4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。

this指针的作用和用途

  1. 当形参和成员变量同名时,可用this指针来区分
  2. 在类的非静态成员函数中返回对象本身,可使用return *this

空指针访问成员函数

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

【面试题】

  1. this指针存在哪里?
    其实编译器在生成程序时加入了获取对象首地址的相关代码。并把获取的首地址存放在了寄存器ECX中(VC++编译器是放在ECX中,其它编译器有可能不同)。也就是成员函数的其它参数正常都是存放在栈中。而this指针参数则是存放在寄存器中。类的静态成员函数因为没有this指针这个参数,所以类的静态成员函数也就无法调用类的非静态成员变量。

  2. this指针可以为空吗?
    可以为空,当我们调用函数时,如果函数内部不需要使用到this,也就是不需要通过this指向当前对象并对其进行操作时才可以为空(当我们在其中什么都不放或者在里面随便打印一个字符串),如果调用的函数需要指向当前对象,并进行操作,则会发生错误(空指针引用)就跟C中一样不能进行空指针的引用

  3. this指针是什么时候创建的?
    this在非静态成员中有意义,作为右值可以直接在编译时确定其存在,运行时无所谓创建。

  4. 我们只有获得一个对象后,才能通过对象使用this指针,如果我们知道一个对象this指针的位置可以直接使用吗?
    this指针只有在非静态成员中才有意义。获得一个对象后,不需要在类外部使用this对其操作。应当注意this是一个右值(方法的一个隐式参数) ,不存在所谓的this的“位置”,只是this表示了对象的存储位置而已。&this违反语义规则,是错误的用法,不会编译通过。

  5. this指针如何传递给类中函数的?绑定?还是在函数参数的首参数就是this指针.那么this指针又是如何找到类实例后函数的?
    this是通过函数参数的首参数来传递的。this指针是在调用之前生成的。类实例后的函数,没有这个说法。类在实例化时,只分配类中的变量空间,并没有为函数分配空间。自从类的函数定义完成后,它就在那儿,不会跑的。


C++对象模型

成员变量和成员函数是分开存储的,只有非静态成员变量才属于类的对象上。

空对象:

  • 空对象占用一个字节的内存空间
  • C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
  • 每个空对象也应该有一个独一无二的内存地址

const修饰成员函数:
常函数:
●成员函数后加const后我们称为这个函数为常函数
●常函数内不可以修改成员属性
●成员属性声明时加关键字mutable后,在常函数中依然可以修改

常对象:
●声明对象前加const称该对象为常对象
●常对象只能调用常函数


类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。一个类在我们不写的情
况下,都会自动生成下面6个默认成员函数:

  1. 构造函数
  2. 拷贝构造函数
  3. 析构函数
  4. 赋值操作符重载
  5. 取地址操作符重载 (很少自己实现)
  6. const修饰的取地址操作符重载(很少自己实现)

构造函数

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员
都有 一个合适的初始值,并且在对象的生命周期内只调用一次。
分类
按参数分:有参构造、无参构造(默认构造)
按类型分:普通构造、拷贝构造
语法
构造函数是特殊的成员函数,需要注意的是,构造函数的虽然名称叫构造,但是需要注意的是构造函数的主要任务并不是开空间创建对象,而是初始化对象。
其特征如下:

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。且只调用一次。
  4. 构造函数可以重载。
  5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
  6. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数。

调用方法(放笔记吧/xk)
C++ —— 类和对象(二)

析构函数

析构函数是特殊的成员函数。
其特征如下:

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值。
  3. 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

拷贝构造函数

只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
拷贝构造函数也是特殊的成员函数,其特征如下:

  1. 拷贝构造函数是构造函数的一个重载形式。
  2. 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
  3. 若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝。
  4. 如果用户定义有参构造函数, C++不在提供默认无参构造,但是会提供默认拷贝构造 ;如果用户定义拷贝构造函数,C++不会再提供其他构造函数

调用方法:(too…)
C++ —— 类和对象(二)
深浅拷贝:
C++ —— 类和对象(二)

成员函数初始化列表

C++ —— 类和对象(二)
(太懒了。。。都没有代码)