什么是类?
在c++中兼容了c语言,并且将struct升级成了类
c语言的结构体在c++里就是类
同时c++中 class 也表示类
那区别在哪里呢?
struct在不写限定符的时候表示全部公有,外部可以调用
class在不写限定符的时候表示全部私有,外部不可以调用
什么是限定符?
限定符: 在类里面 设置了访问权限
private(私有) 不能在类外被直接访问
public(公用)类外可以使用
protected(保护) 不能在类外被直接访问
c++兼容c语言struct 的所有语法
struct 同时升级为了类
类名就是 类型 Stack就是类型 不需要加struct
类里面 可以定义函数
定义类可以用 struct 也可以用 class
不写限定符的时候 class 表示 私有 struct 表示公用
class Stack
{
//类中的访问限定符
//private(私有) 不能在类外被直接访问
//public(公用)类外可以使用
//protected(保护) 不能在类外被直接访问
private:
int* a;
int top;
int capacity;
public:
//默认定义在类里面的函数 是 内联函数 但不一定展开
//正确用法,长的函数声明和定义分离
//短小的函数可以在类里面直接定义x
void Init();
void Push(int x);
bool Empty()
{
return top = 0;
}
};
类中可以干什么?
类中可以定义函数
定义的这个函数只能给这个类使用
同时如果类里面的函数 声明和定义分离的话
那么定义函数的那个文件要写明那个函数属于那个类
#include"Stack.h"
//如果声明和定义分离的话 要讲明属于那个类
void Stack::Init()
{
a = nullptr;
top = 0;
capacity = 10;
}
void Stack::Push(int x)
{
}
struct Queue
{
void Init()
{
}
};
struct ListNode
{
ListNode* next;
int val;
};
什么是对象?
对象:用类 定义的变量
类和对象的关系
类和对象的 关系是 1v多
//类和对象的 关系是 1v多
// 设计图 和 房子
int main()
{
Date d;//对象
Date D;
}
类中的函数
类中的函数都会隐藏一个this 他是一个形参 存在栈帧上
他可以指向传过来的对象
但是不能写在函数的参数上
class Date
{
public:
void Init(int year, int month, int day)
{
// _在c++中惯例中 表示类部的
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << this->_year <<endl << this->_month<<endl << this->_day << endl;
cout << _year << _month << _day << endl;
}
//不能写出来 this
//可以在类里面显示的使用
/*void Print(Date* this)
* //this 是形参 存在在栈帧上的
{
cout << this->_year << this->_month << this->_day << endl;
}*/
//声明不会开辟空间
private:
int _year;
int _month;
int _day;
};
class B
{
};
类和对象的 关系是 1v多
设计图 和 房子
int main()
{
在类中 只计算变量 不计算函数
类中函数放在公共区域 编译完之后是 一段指令
无成员变量的类,对象大小开一个字节,这个字节不存储有效数据
表示定义的对象存在过
Date d;//对象
Date D;
cout << sizeof(d);
cout << sizeof(B);
d.Init(2023, 10, 7);
D.Init(2022, 10, 7);
d.Print();
D.Print();
不能显示的写 this 类似相关的形参和实参
d.Print(&d1);
}
什么是构造函数?
构造函数:
函数名与类名相同
构造函数存在于类中
相当于一个类的初始化
无返回值
对象实例化可以自动调用
可以重载
每一个类如果不自己写构造函数的话那么,它会默认生成构造函数
但是类里面不能有2个无参函数的构造函数
class Date
{
public:
//勾成函数重载 但是无参调用的时候会有歧义
/*Date()
{
_year = 1;
_month = 1;
_day = 1;
} */
/*Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}*/
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
//C++11 开始支持
//还是声明 ,只是声明时给了缺省值
int _year = 1;
int _month = 1;
int _day = 1;
};
构造函数总结
一般情况下都要自己写构造函数
如果成员都是自定义类型,或者声明的时候给了缺省值那么,可以考虑让编译器自动生成
如果有构造函数那么声明的缺省值无效
内置类型 都不处理
什么是默认构造?
我们不写编译默认生成的构造函数,叫默认构造
无参构造函数,也叫默认构造
全缺省也可以叫默认构造
不传参就调用的构造,都叫默认构造
什么是析构函数?
析构函数:
~类名
无返回值
自动调用
类似于销毁
不写的时候编译器自动生产
动态开辟的类都需要
内置类型不处理
自定义类型处理
一个类只能有一个析构函数
class Date
{
public:
//勾成函数重载 但是无参调用的时候会有歧义
/*Date()
{
_year = 1;
_month = 1;
_day = 1;
} */
/*Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}*/
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
//~
~Date()
{
cout << "~Date()" << endl;
}
什么是拷贝构造?
拷贝构造:
跟类名相同
无返回值
拷贝内置类型
自动调用
自定义类型对象传参,必须调用拷贝构造
内置类型可以直接值拷贝
自定义类型成员 则是调用类中的拷贝构造
如果类中动态开辟了,那么都要自写拷贝构造
浅拷贝:
内置类型直接传值调用,不会改变其本身内容
void Test(Date d)
{
//Date d1;
d.Print();
}
深拷贝:
本质是拷贝指向的资源,让你跟我有一样的空间,一样的值
//深拷贝
//本质是拷贝指向的资源,让我跟你有一样的空间,一样的值
Stack(const Stack& d)
{
_array = (int*)malloc(sizeof(int) * d._capacity);
if (_array == NULL)
{
perror("malloc 失败");
return;
}
memcpy(_array, d._array, sizeof(int) * d._size);
_size = d._size;
_capacity = d._capacity;
}