【C++那些事儿】深入理解C++类与对象:从概念到实践(上)| 揭开this指针的神秘面纱
(图片来源网络,侵删)
🔥个人专栏: ✅数据结构冒险记 ✅C++那些事儿
🌅 有航道的人,再渺小也不会迷途。
文章目录
- 1. 面向过程和面向对象初步认识
- 2.类的引入
- 3.类的定义
- 4.类的访问限定符及封装
- 4.1 访问限定符
- 【面试题】
- 问题:C++中struct和class的区别是什么?
- 4.2 封装
- 【面试题】
- 在类和对象阶段,主要是研究类的封装特性,那什么是封装呢?
- 5.类的作用域
- 6.类的实例化
- 7.类对象模型
- 7.1 如何计算类对象的大小
- `问题:类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算一个类的大小?`
- 7.2 类对象的存储方式猜测
- 1. 对象中包含类的各个成员
- 2. 代码只保存一份,在对象中保存存放代码的地址
- 3. 只保存成员变量,成员函数存放在公共的代码段
- 7.3 结构体内存对齐规则
- 8.this指针
- 8.1 this指针的引出
- 8.2 this指针的特性
- 【面试题】
- 1. this指针存在哪里?
- 2. this指针可以为空吗?
- 8.3. C语言和C++实现Stack的对比
- 1. C语言实现
- 2. C++实现
1. 面向过程和面向对象初步认识
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
(图片来源网络,侵删)2.类的引入
C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如:之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现,会发现struct中也可以定义函数。
#include #include using namespace std; typedef int DataType; struct Stack { // 初始化 void Init(size_t capacity) { _array = (DataType*)malloc(sizeof(DataType) * capacity); if (nullptr == _array) { perror("malloc申请空间失败"); return; } _capacity = capacity; _size = 0; } // 入栈 void Push(const DataType& data) { // 扩容 _array[_size] = data; ++_size; } // 取栈顶元素 DataType Top() { return _array[_size - 1]; } // 销毁栈 void Destroy() { if (_array) { free(_array); _array = nullptr; _capacity = 0; _size = 0; } } DataType* _array; size_t _capacity; size_t _size; }; int main() { Stack s; s.Init(10); s.Push(1); s.Push(2); s.Push(3); cout // 类体:由成员函数和成员变量组成 }; // 一定要注意后面的分号 public: void Init(int year) { // 这里的year到底是成员变量,还是函数形参? year = year; } private: int year; }; // 所以一般都建议这样 class Date { public: void Init(int year) { _year = year; } private: int _year; }; // 或者这样 class Date { public: void Init(int year) { mYear = year; } private: int mYear; }; // 其他方式也可以的。一般都是加个前缀或者后缀标识区分就行。 public: // 成员函数声明 void PrintPersonInfo(); private: char _name[20]; char _gender[3]; int _age; }; // 这里需要指定PrintPersonInfo是属于Person这个类域(成员函数类外定义) void Person::PrintPersonInfo() { cout Person._age = 100; // 编译失败:error C2059: 语法错误:“.” return 0; } public: void PrintA() { cout public: void f1() {} private: int _a; }; // 类中仅有成员函数 class A2 { public: void f2() {} }; // 类中什么都没有---空类 class A3 {}; int main() { cout public: void Init(int year, int month, int day) { _year = year; _month = month; _day = day; } void Print() { cout Date d1, d2; d1.Init(2022, 1, 11); d2.Init(2022, 1, 12); d1.Print(); d2.Print(); return 0; } public: void PrintA() { cout A* p = nullptr; p-PrintA(); return 0; } // 答案:C、正常运行 // 原因:PrintA函数不在某个实例化的对象中,而是在公共代码区,所以p不会解引用,但是此处的p的作用是作为函数实参传递给函数第一个隐含的this指针。 // 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行 class A { public: void PrintA() { cout A* p = nullptr; p-PrintA(); return 0; } // 答案:B、运行崩溃 // 原因:PrintA函数中访问了成员函数_a,而_a的访问需要解引用this指针,但此时的this指针就是p,p是空指针,空指针解引用导致程序运行崩溃 DataType* array; int capacity; int size; }Stack; void StackInit(Stack* ps) { assert(ps); ps-array = (DataType*)malloc(sizeof(DataType) * 3); if (NULL == ps-array) { assert(0); return; }ps-capacity = 3; ps-size = 0; } void StackDestroy(Stack* ps) { assert(ps); if (ps-array) { free(ps-array); ps-array = NULL; ps-capacity = 0; ps-size = 0; } } void CheckCapacity(Stack* ps) { if (ps-size == ps-capacity) { int newcapacity = ps-capacity * 2; DataType* temp = (DataType*)realloc(ps-array, newcapacity * sizeof(DataType)); if (temp == NULL) { perror("realloc申请空间失败!!!"); return; } ps-array = temp; ps-capacity = newcapacity; } } void StackPush(Stack* ps, DataType data) { assert(ps); CheckCapacity(ps); ps-array[ps-size] = data; ps-size++; } int StackEmpty(Stack* ps) { assert(ps); return 0 == ps-size; } void StackPop(Stack* ps) { if (StackEmpty(ps)) return; ps-size--; } DataType StackTop(Stack* ps) { assert(!StackEmpty(ps)); return ps-array[ps-size - 1]; } int StackSize(Stack* ps) { assert(ps); return ps-size; } int main() { Stack s; StackInit(&s); StackPush(&s, 1); StackPush(&s, 2); StackPush(&s, 3); StackPush(&s, 4); printf("%d\n", StackTop(&s)); printf("%d\n", StackSize(&s)); StackPop(&s); StackPop(&s); printf("%d\n", StackTop(&s)); printf("%d\n", StackSize(&s)); StackDestroy(&s); return 0; } public: void Init() { _array = (DataType*)malloc(sizeof(DataType) * 3); if (NULL == _array) { perror("malloc申请空间失败!!!"); return; } _capacity = 3; _size = 0; } void Push(DataType data) { CheckCapacity(); _array[_size] = data; _size++; } void Pop() { if (Empty()) return; _size--; } DataType Top() { return _array[_size - 1]; } int Empty() { return 0 == _size; } int Size() { return _size; } void Destroy() { if (_array) { free(_array); _array = NULL; _capacity = 0; _size = 0; } } private: void CheckCapacity() { if (_size == _capacity) { int newcapacity = _capacity * 2; DataType* temp = (DataType*)realloc(_array, newcapacity *sizeof(DataType)); if (temp == NULL) { perror("realloc申请空间失败!!!"); return; } _array = temp; _capacity = newcapacity; } } private: DataType* _array; int _capacity; int _size; }; int main() { Stack s; s.Init(); s.Push(1); s.Push(2); s.Push(3); s.Push(4); printf("%d\n", s.Top()); printf("%d\n", s.Size()); s.Pop(); s.Pop(); printf("%d\n", s.Top()); printf("%d\n", s.Size()); s.Destroy(); return 0; }
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。
还没有评论,来说两句吧...