移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——2.类和对象(上)

1. 类的定义

• class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后⾯分号不能省 略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的⽅法或 者成员函数。

• C++中struct也可以定义类,C++兼容C中struct的⽤法,同时struct升级成了类,明显的变化是 struct中可以定义函数,⼀般情况下我们还是推荐⽤class定义类。

• 定义在类⾯的成员函数默认为inline。

#include<iostream>
using namespace std;
class Stack
{
  public:
  // 成员函数
  void Init(int n = 4)
 {
  array = (int*)malloc(sizeof(int) * n);
  if (nullptr == array)
    {
     perror("malloc申请空间失败");
     return;
    }
  capacity = n;
  top = 0;
 }

  void Push(int x)
 {
   // ...扩容
   array[top++] = x;
 }

 int Top()
 {
  assert(top > 0);
  return array[top - 1];
  }

  void Destroy()
  {
   free(array);
   array = nullptr;
   top = capacity = 0;
  }

private:
// 成员变量
int* array;
size_t capacity;
size_t top;
}; // 分号不能省略

1.1 访问限定符 

• public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访 问,protected和private是⼀样的,以后继承章节才能体现出他们的区别。

• class定义成员没有被访问限定符修饰时默认为private,struct默认为public。

• ⼀般成员变量都会被限制为private/protected,需要给别⼈使⽤的成员函数会放为public。 

2 对象⼤⼩ 

对 象中是否有存储指针的必要呢,Date实例化d1和d2两个对象,d1和d2都有各⾃独⽴的成员变量 _year/_month/_day存储各⾃的数据,但是d1和d2的成员函数Init/Print指针却是⼀样的,存储在对象 中就浪费了。如果⽤Date实例化100个对象,那么成员函数指针就重复存储100次,太浪费了

 上⾯我们分析了对象中只存储成员变量

没有成员变量的类对象的⼤⼩是1,为什么没有成员变量还要给1个 字节呢?因为如果⼀个字节都不给,怎么表⽰对象存在过呢!所以这⾥给1字节,纯粹是为了占位标识 对象存在。

2.1 内存对齐

内存对⻬规则

• 第⼀个成员在与结构体偏移量为0的地址处。

• 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。

• 注意:对⻬数 = 编译器默认的⼀个对⻬数 与 该成员⼤⼩的较⼩值。

• VS中默认的对⻬数为8

• 结构体总⼤⼩为:最⼤对⻬数(所有变量类型最⼤者与默认对⻬参数取最⼩)的整数倍。

• 如果嵌套了结构体的情况,嵌套的结构体对⻬到⾃⼰的最⼤对⻬数的整数倍处,结构体的整体⼤⼩ 就是所有最⼤对⻬数(含嵌套结构体的对⻬数)的整数倍。

3.this指针

• Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调⽤Init和 Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?那么这⾥就要看到C++给了 ⼀个隐含的this指针解决这⾥的问题

• 编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this 指针。⽐如Date类的Init的真实原型为, void Init(Date* const this, int year, int month, int day)

• 类的成员函数中访问成员变量,本质都是通过this指针访问的,如Init函数中给_year赋值, this- >_year = year;

• C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显 ⽰使⽤this指针。

#include<iostream>
using namespace std;
class Date
{
  public:
  // void Init(Date* const this, int year, int month, int day)
  void Init(int year, int month, int day)
{
  // 编译报错:error C2106: “=”: 左操作数必须为左值,this为常量,无法赋值
  // this = nullptr;
  // this->_year = year;
  _year = year;
this->_month = month;
this->_day = day;
}

void Print()

{
cout << _year << "/" << _month << "/" << _day << endl;
}

private:
// 这⾥只是声明,没有开空间
int _year;
int _month;
int _day;
};

(3)this指针是存在哪里的?a.栈  b.堆  c.静态区  d.常量区

答案:a

解释:this指针是个形参,形参是在函数的栈桢里,在函数的栈桢里面的变量是属于栈中的。有时编译器会使用寄存器对其进行优化,this指针会存在寄存器中。

4. C++和实现Stack 

#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
  public:
  // 成员函数
  void Init(int n = 4)
  {
    _a = (STDataType*)malloc(sizeof(STDataType) * n);
    if (nullptr == _a)
     {
       perror("malloc申请空间失败");
       return;
     }
     _capacity = n;
     _top = 0;
  }

  void Push(STDataType x)
   {
     if (_top == _capacity)
       {
         int newcapacity = _capacity * 2;
         STDataType* tmp = (STDataType*)realloc(_a, newcapacity *sizeof(STDataType));
         if (tmp == NULL)
          {
            perror("realloc fail");
            return;
          }
     _a = tmp;
     _capacity = newcapacity;
       }
    _a[_top++] = x;
  }

   void Pop()
   {
     assert(_top > 0);
     --_top;
   }

   bool Empty()
   {
     return _top == 0;
    }

   int Top()
   {
     assert(_top > 0);
     return _a[_top - 1];
   }

  void Destroy()
  {
    free(_a);
    _a = nullptr;
    _top = _capacity = 0;
  }

  private:
   STDataType* _a;
   size_t _capacity;
   size_t _top;
};

  • 101
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 49
    评论
评论 49
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值