class类:
相当于C语言结构体,不过里面可以包含各种函数,有公有区域public和私有区域private,只有在类中的成员函数或成员变量可以访问私有区域。类中自带两个初始化函数:构造函数和析构函数
在Date类中的函数,为了能让主函数识别多个Date类型的变量,类中的函数一般都自带 Date* this 的一个形参,来识别是那个Date类型变量,当然函数中也可以调用this
private中的成员变量都是声明,并不没有开空间,且独立存储,当类对象实例化后
Data d1; 才会开空间
class Date //类
{
public://公有 声明在public后面的成员所有人都是可以使用
//void Init(Date* this,编译器增加的 存在栈中 int year,int month,int day)
void Init(int year,int month,int day)//成员函数是一样的,放到公共区域(代码段)
{
_year=year;
_month=month;
this->_day=day;//可以调用this
cout << this << endl; //可以在函数里面调用this 输出地址
}
void func1()
{
cout << "func()" << endl;
}
//private://私有 只有类内的成员函数才可以访问
int _year; //声明 没开空间
int _month; //成员变量是不一样的要独立存储
int _day;
};
class A
{};//为空的类 被实例化时会有1byte的占位大小
int test1()
{
Date d1; //类对象实例化 -- 开空间
//d1.Init(&d1,2023,2,2); 编译器会给d1地址给函数Init
d1.Init(2023,2,2);
cout << d1._year << endl;
cout << sizeof(d1) << endl;//只有成员变量占位 成员函数在公共区域
A A1;
cout << sizeof(A1) << endl;//为空的类 被实例化时会有1byte的占位大小
Date* ptr= nullptr;
ptr->func1(); //正常运行
(*ptr).func1(); //正常运行
//ptr->Init(2023,2,2) //运行崩溃 ptr是空地址 会传给this this->_year会崩溃 this是空指针
return 0;
}
构造函数和析构函数
//构造函数——对象实例化时编译器自动调用,函数名与类名相同,无返回值所以不用加类型,可重载 //析构函数——对象生命周期结束时自动调用,函数名是在类名前加上~,一个类只能有一个析构函数,不能重载
class Stack
{
public:
Stack()
{
cout << "Stack()" << endl;
_a= nullptr;
_size=0;
_capacity=0;
}
Stack(int n)//可以有多个构造函数
{
cout << "Stack(int n)" << endl;
_a=(int*)malloc(sizeof(int)*n);//开辟空间
if(_a== nullptr)
{
perror("malloc error");
exit(-1);
}
_capacity=n;
_size=0;
}
~Stack()
{
cout << "~Stack()" << endl;
if(_a)
{
free(_a);
_a = nullptr;
_size=_capacity=0;
}
}
private:
int* _a;
int _size;
int _capacity;
};
int test2()//构造函数和析构函数
{
Stack st1;
Stack st2(4);
return 0;
}
//默认生成构造和析构函数、拷贝构造
如果写了任意一个构造函数,编译器就不会生成默认的构造函数
不处理内置类型,处理自定义类型
tip:内置类型:int/char/double.... 自定义类型:class/struct.....
operator 重载复用
变量的构造、析构和栈一样,先进后析构,后进的先析构
class Date2
{
public://如果写了任意一个构造函数,编译器就不会生成默认的构造函数
Date2(int year,int month,int day)
{
cout << "Date2()" << endl;
_year=year;
_month=month;
_day=day;
}
//拷贝构造
Date2(const Date2& d)//const:防止修改引用的参数中的数据 传引用传参 如果传形参 会无限递归
{
cout << "Date2(const Date2& d)" << endl;
_year=d._year;//防止写反⬆
_month=d._month;
_day=d._day;
}
bool operator==(const Date2& d)//两个参数 一个this 一个d
{
return _year==d._year
&& _month==d._month
&& _day==d._day;
}
bool operator<(const Date2& d)
{
return
_year<d._year||
_year==d._year && _month<d._month||
_year==d._year && _month==d._month&&_day<d._day;
}
bool operator<=(const Date2& d)//复用
{
return *this == d || *this < d;
}
bool operator>(const Date2& d)
{
return !(*this <=d);
}
bool operator>=(const Date2& d)
{
return *this > d || *this == d;
}
bool operator!=(const Date2& d)
{
return !(*this == d);
}
Date2& operator=(const Date2& d)//返回引用参数 支持连续赋值 d1=d2=d3
{
if(this==&d) return *this;//d1=d1自己给自己赋值直接返回
_year=d._year;
_month=d._month;
_day=d._day;
return *this;
}
void Print()
{
cout << _year << " ";
cout << _month << " ";
cout << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
class MyQueue
{
public:
//默认生成的构造函数对内置类型不处理,只处理自定义类型
void Print()
{
_day=10;//假如这个是构造函数内的
cout << _year << " ";
cout << _month << " ";
cout << _day << endl;
}
Stack _pushST;
Stack _popST;
int size;//clion编译器初始化会变成 1
private:
//声明位置给缺省值,如果没自定义构造函数,则内置类型用缺省值
int _year=2023;
int _month=2;
int _day=3;
};
//tip:内置类型:int/char/double.... 自定义类型:class/struct.....
//默认生成的构造函数、析构函数,不处理内置类型,处理自定义类型
int test3()//默认生成构造和析构函数、拷贝构造
{ //tip:如果没写上面两个构造函数
//Date2 d1(); (年月日是随机值) 可以编译,用编译器自动生成的 无参的构造函数,
Date2 d1(2023,2,3);
//拷贝构造
Date2 d2(d1); //两种拷贝
Date2 d3=d1;
//默认构造、析构函数测试
MyQueue q;
q.Print();
return 0;
}
//深 拷贝函数
全缺省构造和无参构造冲突,半缺省不会
如果不开辟空间再拷贝过去,st1._array和st2._array会共用一个地址 崩溃
typedef int DateType;
class Stack2
{
public:
// Stack2()
// {
// cout << "Stack2()" << endl;
//
// _array= nullptr;
// _size=0;
// _capacity=0;
// }
Stack2(int n=10)//tip:全缺省构造和无参构造冲突,半缺省不会
{
cout << "Stack2(int n=10)" << endl;
_array=(DateType *)malloc(sizeof(DateType)*n);
if(_array== nullptr)
{
perror("malloc error");
exit(-1);
}
_capacity=n;
_size=0;
}
Stack2(const Stack2& st)//深拷贝 如果不开辟空间再拷贝过去,st1._array和st2._array会共用一个地址 崩溃
{
cout << "Stack2(const Stack2& st)" << endl;
_array=(DateType*)malloc(sizeof(DateType)*st._size);
if(_array== nullptr)
{
perror("malloc error");
exit(-1);
}
_size=st._size;
_capacity=st._capacity;
memcpy(_array,st._array,st._capacity);
}
~Stack2()
{
cout << "~Stack2()" << endl;
if(_array)
{
free(_array);
_array = nullptr;
_size=_capacity=0;
}
}
private:
DateType* _array;
int _size;
int _capacity;
};
int test4()//深 拷贝函数
{
Stack2 st;//tip:无参(不加括号)使用的是全缺省构造,编译器分不出来全缺省和无参构造,会冲突
Stack2 st1(20);
Stack2 st2(st1);//这种情况如果不写拷贝构造,Stack2中的数组_array共用一个地址,当st2析构后,st1的就是野指针,会崩溃
//和栈一样 先进后析构,后进的先析构
return 0;
}
//构造和析构的先后顺序
全局变量先构造,局部变量再按顺序构造(不分静态),然后按照动态后入先析构,析构完动态后再静态,后入先析构
class AA
{
public:
AA()
{
cout << "AA" << endl;
}
~AA()
{
cout << "~AA" << endl;
}
};
class BB {
public:
BB() {
cout << "BB" << endl;
}
~BB() {
cout << "~BB" << endl;
}
};
class CC
{
public:
CC()
{
cout << "CC" << endl;
}
~CC()
{
cout << "~CC" << endl;
}
};
class DD
{
public:
DD()
{
cout << "DD" << endl;
}
~DD()
{
cout << "~DD" << endl;
}
};
// CC c;
int test6()//构造和析构的先后顺序 全局先构造 局部再按顺序构造(不分静态) 然后按照动态后入先析构 析构完动态后再静态,后入先析构
{
//入栈顺序为 C A B D 出栈顺序为 B A D C
AA a;
BB b;//等B A 析构完后再析构D C 全局最后析构
static DD d;
return 0;
}