目录
1. 类对象模型
1.1 如何计算类对象的大小
1.2 类对象的存储方式
1.3 结构体内存对齐规则
2. this指针
2.1 this指针的引出
2.2 this指针的特性
3. 类的6个默认成员函数
4.构造函数
4.1 概念
4.2 特性
1. 类对象模型
1.1 如何计算类对象的大小
class A{public :void PrintA (){cout << _a << endl ;}private :char _a ;};
 
 问题:类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算  
 
 
 一个类的大小? 
 
 
1.2 类对象的存储方式
 
 结论:一个类的大小,实际就是该类中 
 ” 
 成员变量 
 ” 
 之和,当然要注意内存对齐  
 
 
 注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。  
 
 
1.3 结构体内存对齐规则
1. 第一个成员在与结构体偏移量为 0 的地址处。2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。VS 中默认的对齐数为 83. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
2. this指针
2.1 this指针的引出
 
 我们先来定义一个日期类  
 Date  
 
class Date
{ 
public:
 void Init(int year, int month, int day)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 void Print()
 {
 cout <<_year<< "-" <<_month << "-"<< _day <<endl;
 }
private:
 int _year;     // 年
 int _month;    // 月
 int _day;      // 日
};
int main()
{
 Date d1, d2;
 d1.Init(2022,1,11);
 d2.Init(2022, 1, 12);
 d1.Print();
 d2.Print();
 return 0;
} 
  对于上述类,有这样的一个问题:  
 
 
  
  Date 
  类中有 
   Init  
  与 
   Print  
  两个成员函数,函数体中没有关于不同对象的区分,那当 
  d1 
  调用 
   Init  
  函  
 
 
  
  数时,该函数是如何知道应该设置 
  d1 
  对象,而不是设置 
  d2 
  对象呢?  
 
 
  
  C++ 
  中通过引入 
  this 
  指针解决该问题,即: 
  C++ 
  编译器给每个 
  “ 
  非静态的成员函数 
  “ 
  增加了一个隐藏  
 
 
  
  的指针参数,让该指针指向当前对象 
  ( 
  函数运行时调用该函数的对象 
  ) 
  ,在函数体中所有 
  “ 
  成员变量 
  ”  
 
 
  
  的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编  
 
 
  
  译器自动完成 
  。 
 
 
  
 2.2 this指针的特性
 
  1.  
  this 
  指针的类型:类类型 
  * const 
  ,即成员函数中,不能给 
  this 
  指针赋值。  
 
 
  
  2.  
  只能在 
  “ 
  成员函数 
  ” 
  的内部使用  
 
 
  
  3.  
  this 
  指针本质上是 
  “ 
  成员函数 
  ” 
  的形参 
  ,当对象调用成员函数时,将对象地址作为实参传递给  
 
 
  
  this 
  形参。所以 
  对象中不存储 
  this 
  指针 
  。  
 
 
  
  4.  
  this 
  指针是 
  “ 
  成员函数 
  ” 
  第一个隐含的指针形参,一般情况由编译器通过 
  ecx 
  寄存器自动传  
 
 
  
  递,不需要用户传递 
 
 
  
 3. 类的6个默认成员函数
 
  如果一个类中什么成员都没有,简称为空类。  
 
 
  
  空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下 
  6 
  个默认成员  
 
 
  
  函数。  
 
 
  
  默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。  
 
 
 class Date {};
 
 
4.构造函数
4.1 概念
 
 对于以下 
 Date 
 类:  
 
class Date
{
public:
 void Init(int year, int month, int day)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 void Print()
 {
 cout << _year << "-" << _month << "-" << _day << endl;
 }
private:
 int _year;
 int _month;
 int _day;
};
int main()
{
 Date d1;
 d1.Init(2022, 7, 5);
 d1.Print();
 Date d2;
 d2.Init(2022, 7, 6);
 d2.Print();
 return 0;
} 
  对于 
  Date 
  类,可以通过 
   Init  
  公有方法给对象设置日期,但如果每次创建对象时都调用该方法设置  
 
 
  
  信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢?  
 
 
  
  
  构造函数 
  是一个 
  特殊的成员函数,名字与类名相同 
  , 
  创建类类型对象时由编译器自动调用 
  ,以保证  
 
 
  
  每个数据成员都有 一个合适的初始值,并且 
  在对象整个生命周期内只调用一次 
  。 
 
 
  
 4.2 特性
 
  构造函数 
  是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任  
 
 
  
  务 
  并不是开空间创建对象,而是初始化对象 
  。  
 
 
  
  
  其特征如下:  
 
 
  
          1. 函数名与类名相同。  
 
 
  
          2. 无返回值。  
 
 
  
          3. 对象实例化时编译器 
  自动调用 
  对应的构造函数。  
 
 
  
          4. 构造函数可以重载。 
 
 
  class Date
 {
  public:
      // 1.无参构造函数
      Date()
     {}
  
      // 2.带参构造函数
      Date(int year, int month, int day)
     {
          _year = year;
          _month = month;
          _day = day;
     }
  private:
      int _year;
      int _month;
      int _day;
 };
  
  void TestDate()
 {
      Date d1; // 调用无参构造函数
      Date d2(2015, 1, 1); // 调用带参的构造函数
  
      // 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
      // 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
      // warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)
      Date d3();
 } 
           5. 如果类中没有显式定义构造函数,则 
   C++ 
   编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。 
  
 
   class Date
 {
  public:
 /*
 // 如果用户显式定义了构造函数,编译器将不再生成
 Date(int year, int month, int day)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 */
 
 void Print()
 {
 cout << _year << "-" << _month << "-" << _day << endl;
 }
  
  private:
 int _year;
 int _month;
 int _day;
 };
  
  int main()
 {
 // 将Date类中构造函数屏蔽后,代码可以通过编译,因为编译器生成了一个无参的默认构造函
数
 // 将Date类中构造函数放开,代码编译失败,因为一旦显式定义任何构造函数,编译器将不再
生成
      // 无参构造函数,放开后报错:error C2512: “Date”: 没有合适的默认构造函数可用
 Date d1;
 return 0;
 } 
    6.  
    关于编译器生成的默认成员函数,很多人会有疑惑:不实现构造函数的情况下,编译器会  
   
 
    
    生成默认的构造函数。但是看起来默认构造函数又没什么用? 
    d 
    对象调用了编译器生成的默  
   
 
    
    认构造函数,但是 
    d 
    对象 
    _year/_month/_day 
    ,依旧是随机值。也就说在这里 
    编译器生成的  
   
 
    
    默认构造函数并没有什么用??  
   
 
    
    解答: 
    C++ 
    把类型分成内置类型 
    ( 
    基本类型 
    ) 
    和自定义类 
    型。内置类型就是语言提供的数据类  
   
 
    
    型,如: 
    int/char... 
    ,自定义类型就是我们使用 
    class/struct/union 
    等自己定义的类型,看看  
   
 
    
    下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员 
    _t 
    调用的它的默认成员  
   
 
    
    函数。  
   
 
   class Time
{
public:
 Time()
 {
 cout << "Time()" << endl;
 _hour = 0;
 _minute = 0;
 _second = 0;
 }
private:
 int _hour;
 int _minute;
 int _second;
};
class Date
{
private:
 // 基本类型(内置类型)
 int _year;
 int _month;
 int _day;
 // 自定义类型
 Time _t;
};
int main()
{
 Date d;
 return 0;
} 
 注意: 
 C++11  
 中针对内置类型成员不初始化的缺陷,又打了补丁,即: 
 内置类型成员变量在  
 
 
 类中声明时可以给默认值 
 
class Time
{
public:
 Time()
 {
 cout << "Time()" << endl;
 _hour = 0;
 _minute = 0;
 _second = 0;
 }
private:
 int _hour;
 int _minute;
 int _second;
};
class Date
{
private:
 // 基本类型(内置类型)
 int _year = 1970;
 int _month = 1;
 int _day = 1;
 // 自定义类型
 Time _t;
};
int main()
{
 Date d;
 return 0;
} 
  7.  
  无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。  
 
 
  
  注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为  
 
 
  
  是默认构造函数。 
 
 


![[Netty] HashWheelTimer时间轮 (十六)](https://img-blog.csdnimg.cn/739e81dddd064321ae7e155dc8343809.png)
















