面向对象和面向对象的认识
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
就拿洗衣服来说
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完
成。
类的引入
我们知道C语言的struct的结构体只能定义变量,不能定义函数,所以我们只能在结构体外定义,但在c++中不仅继承了C语言的struct的所有用法,还补充了C语言结构体不能定义函数的用法
#include<iostream> #include<stdlib.h> using std::cout; using std::endl; using std::cin; struct SList { int* a; int top; int capacity; //插入 void Push(int x) { if (top == capacity) { //扩容 int t = capacity > 0 ? 2 * capacity : 4; int* tmp = (int*)realloc(a, sizeof(int) * t); if (tmp == NULL) { perror("ralloc"); return; } capacity = t; a = tmp; } a[top] = x; top++; } //初始化 void Init() { a = NULL; top = 0;//栈底元素下一个 capacity = 0; } //删除 void Pop() { top--; } }; int main() { SList stack; stack.Init(); stack.Push(4); stack.Push(3); stack.Push(2); stack.Push(1); stack.Pop(); return 0; }
类的定义
相比于struct定义类,c++更喜欢使用class来定义
class className { // 类体:由成员函数和成员变量组成 }; // 一定要注意后面的分号
class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分
号不能省略。
类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
访问限定符
类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用
访问限定符有三种 public、protected private
#include<iostream> #include<stdlib.h> using std::cout; using std::endl; using std::cin; class SList { protected: int* a; int top; int capacity; public: //插入 void Push(int x) { if (top == capacity) { //扩容 int t = capacity > 0 ? 2 * capacity : 4; int* tmp = (int*)realloc(a, sizeof(int) * t); if (tmp == NULL) { perror("ralloc"); return; } capacity = t; a = tmp; } a[top] = x; top++; } //初始化 void Init() { a = NULL; top = 0;//栈底元素下一个 capacity = 0; } //删除 void Pop() { top--; } }; int main() { SList stack; stack.Init(); stack.Push(4); stack.Push(3); stack.Push(2); stack.Push(1); stack.Pop(); return 0; }
【访问限定符说明】
- public修饰的成员在类外可以直接被访问
- protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
- 如果后面没有访问限定符,作用域就到 } 即类结束。
- class的默认访问权限为private,struct为public(因为struct要兼容C)
类的方法声明和定义分离
在类中,函数的定义有两种,
一种是在类的内部进行定义,编译器可能会将其当成内联函数处理。相当于函数被inline修饰了,至于会不会被展开,由编译器决定的>。
上面的代码就是在类的内部定义的
另一种就是在头文件里面声明,然后在其他cpp文件定义
头文件
#include<iostream> #include<stdlib.h> using std::cout; using std::endl; using std::cin; class SList { protected: int* a; int top; int capacity; public: void Push(int x); void Init(); //删除 void Pop() { top--; } };
cpp文件
#include"day2_1.h" //插入 void SList::Push(int x) { if (SList::top == capacity) { //扩容 int t = capacity > 0 ? 2 * capacity : 4; int* tmp = (int*)realloc(a, sizeof(int) * t); if (tmp == NULL) { perror("ralloc"); return; } capacity = t; a = tmp; } a[top] = x; top++; } //初始化 void SList::Init() { a = nullptr; top = 0;//栈底元素下一个 capacity = 0; } int main() { SList stack; stack.Init(); stack.Push(4); stack.Push(3); stack.Push(2); stack.Push(1); stack.Pop(); return 0; }
函数里面的变量会先在当前的{}里面找,找不到就会去对应的类里面找
我们在看到很多人写的c++代码里面的成员很多都会加 -
class Date { public: void Init(int year, int month, int day) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; };
封装
C++中的封装是面向对象编程的特性之一,它允许将数据和操作封装在类的内部,对外部隐藏实现细节。通过使用访问修饰符(public、private、protected),可以控制类成员的访问权限,实现数据的安全性和可控性。
类的作用域
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 ::
作用域操作符指明成员属于哪个类域。
类的实例化
class Date { public: void Init(int year, int month, int day) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; };
这个只叫定义类,没有实例化对象
int main() { Date data; data.Init(2024, 1, 1); }
当我们使用这个类来创建一个变量,就是实例化对象
一个类可以实例化很多个对象
类的大小
#include<iostream> #include<stdlib.h> using std::cout; using std::endl; using std::cin; class Date { public: void Init(int year, int month, int day) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; }; int main() { Date data; data.Init(2024, 1, 1); Date data1; data1.Init(2024, 1, 1); Date data2; data2.Init(2024, 1, 1); cout << sizeof(Date); }
可以发现类的大小是12,所以可以说明,类的方法的大小在类中不计算(内存对齐)
在反汇编中我们可以看到,不同对象的类的方法的地址是一样的,而不同对象的成员是不一样的,
c++初阶-------类和对象-2