1. 面向过程和面向对象初步认识
面向对象过程更注重步骤
面向对象更注重几个对象之间的联系
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
2. 类的引入
在 C 语言 中 结构体只能定义变量,而在 C++中,结构体不仅可以定义变量,还可以定义函数
代码举例
#include<iostream> #include<stdlib.h> using namespace std; struct stack { void Init(int n = 4) { int* pa = (int*)malloc(sizeof(int) * n); if (pa == nullptr) { perror("malloc fail"); return; } _a = pa; _top = 0; _capacity = n; } void Push(int x) { if (_top == _capacity) { int* pa = (int*)realloc(_a,sizeof(int) * _capacity * 2); if (pa == nullptr) { perror("realloc fail"); return; } _a = pa; _capacity *= 2; } _a[_top++] = x; } void Print() { for (int i = 0; i < _top; i++) { cout << _a[i] << " "; } cout << endl; } int* _a; int _top; int _capacity; }; int main() { stack st; //C++支持类的名称也是类型 st.Init(); st.Push(1); st.Push(2); st.Push(4); st.Push(3); st.Push(2); st.Print(); return 0; }
上面结构体的定义,在 C++ 中更喜欢用 class 来代替。
3. 类的定义
class ClassName
{
; // 由 类的变量和类的函数 组成
}; //分号不要遗忘
class为定义类的关键字,ClassName为类的名字,{}中为类的主体
类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
类的两种定义方式:
1. 声明和定义全部放在类体中(需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。)
2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,(注意:成员函数名前需要加类名::)
代码举例(struct)
stack.h:
#include<iostream> #include<stdlib.h> using namespace std; struct stack { void Init(int n = 4); void Push(int x); void Print(); int* _a; int _top; int _capacity; };
stack.cpp:
#include "stack.h" void stack ::Init(int n) { int* pa = (int*)malloc(sizeof(int) * n); if (pa == nullptr) { perror("malloc fail"); return; } _a = pa; _top = 0; _capacity = n; } void stack::Push(int x) { if (_top == _capacity) { int* pa = (int*)realloc(_a, sizeof(int) * _capacity * 2); if (pa == nullptr) { perror("realloc fail"); return; } _a = pa; _capacity *= 2; } _a[_top++] = x; } void stack::Print() { for (int i = 0; i < _top; i++) { cout << _a[i] << " "; } cout << endl; }
test.cpp:
#include "stack.h" int main() { stack st; st.Init(); st.Push(1); st.Push(2); st.Push(4); st.Push(3); st.Push(2); st.Print(); return 0; }
运行结果:
成员变量命名规则的建议:
建议在最前面或者最后面加一个 _ (防止与函数的形参名字相撞)
代码举例(class)
stack.h:
#include<iostream> #include<stdlib.h> using namespace std; class stack { public: //类的访问限定符 void Init(int n = 4); void Push(int x); void Print(); private: //类的访问限定符 int* _a; int _top; int _capacity; };
stack.cpp:
#include "stack.h" void stack ::Init(int n) { int* pa = (int*)malloc(sizeof(int) * n); if (pa == nullptr) { perror("malloc fail"); return; } _a = pa; _top = 0; _capacity = n; } void stack::Push(int x) { if (_top == _capacity) { int* pa = (int*)realloc(_a, sizeof(int) * _capacity * 2); if (pa == nullptr) { perror("realloc fail"); return; } _a = pa; _capacity *= 2; } _a[_top++] = x; } void stack::Print() { for (int i = 0; i < _top; i++) { cout << _a[i] << " "; } cout << endl; }
test.cpp:
#include "stack.h" int main() { stack st; st.Init(); st.Push(1); st.Push(2); st.Push(4); st.Push(3); st.Push(2); st.Print(); return 0; }
4. 类的访问限定符及封装
a. 类的访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
【访问限定符说明】
1. public修饰的成员在类外可以直接被访问
2. protected 和 private修饰的成员在类外不能直接被访问(此处protected 和 private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. 如果后面没有访问限定符,作用域就到 } 即类结束。
举例
5. class的默认访问权限为 private ,struct 为 public (因为struct要兼容C)
b. 封装
在类和对象阶段,主要是研究类的封装特性,那什么是封装呢?
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装本质上是一种管理,让用户更方便使用类。
在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。
5. 类的作用域
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。
举例
6. 类的实例化
用类类型创建对象的过程,称为类的实例化(实例化是一定要开空间的)
举例
7. 类对象模型
a. 如何计算类对象的大小
只计算 类的变量的大小(详细 C语言初阶:结构体(进阶) )
代码举例
#include <iostream>
using namespace std;
struct st
{
int ADD()
{
return n + m;
}
int n;
int m;
};
int main()
{
int sz = sizeof(st);
cout << sz << endl;
return 0;
}
运行结果:
b. 对类对象的存储方式猜测
- 对象中包含类的各个成员
如果成员是 函数:
那么应该存在 代码段
如果成员是 变量:
那么应该存在 栈区
所以 计算类对象的大小,就是计算类的变量的大小(详细 http://t.csdnimg.cn/v9tpm )
代码举例
#include <iostream> using namespace std; struct st { int ADD() { return n + m; } int n; int m; }; int main() { int sz = sizeof(st); cout << sz << endl; return 0; }
运行结果:
- 对象中只有类的函数
因为类的实例化是一定会开辟空间的,所以编译器给了一个字节来唯一标识这个类的对象
代码举例
#include <iostream> using namespace std; struct st { int ADD(int x,int y) { return x + y; } }; int main() { int sz = sizeof(st); cout << sz << endl; return 0; }
运行结果:
- 对象中什么都没有(空类)
空类比较特殊,所以 编译器给了空类一个字节来唯一标识这个类的对象
代码举例
#include <iostream> using namespace std; struct st { }; int main() { int sz = sizeof(st); cout << sz << endl; return 0; }
运行结果:
8. this指针
同一个类创建不同的对象,由于类的成员函数是不在栈区里面(即不在类里面),那编译器怎么知道哪个对象的对应的成员函数
这个时候,编译器做了一个处理:增加了一个 this 指针
代码举例
#include<iostream> #include<stdlib.h> using namespace std; struct stack { void Init(int n = 4) { int* pa = (int*)malloc(sizeof(int) * n); if (pa == nullptr) { perror("malloc fail"); return; } _a = pa; _top = 0; _capacity = n; } void Push(int x) { if (_top == _capacity) { int* pa = (int*)realloc(_a, sizeof(int) * _capacity * 2); if (pa == nullptr) { perror("realloc fail"); return; } _a = pa; _capacity *= 2; } _a[_top++] = x; } void Print() { for (int i = 0; i < _top; i++) { cout << _a[i] << " "; } cout << endl; } int* _a; int _top; int _capacity; }; int main() { stack st; //C++支持类的名称也是类型 st.Init(); st.Push(1); st.Push(2); st.Push(4); st.Push(3); st.Push(2); st.Print(); return 0; }
this 指对应的类的对象的地址
注意事项:
1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
2. 只能在“成员函数”的内部使用
3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过 ecx 寄存器自动传递,不需要用户传递
代码举例
#include<iostream> #include<stdlib.h> using namespace std; struct date { int _year; int _month; int _day; void Init(int year, int month, int day) { _year = year; _month = month; _day = day; cout << this->_year << endl; cout << this->_month << endl; cout << this->_day << endl; } }; int main() { date st; st.Init(2024, 1, 4); return 0; }
运行结果:
版权声明:本文为博主作者:小小小汐-原创文章,版权归属原作者,如果侵权,请联系我们删除!
原文链接:https://blog.csdn.net/2301_79789645/article/details/135406352