秒收录网站,广州互联网设计公司,seo关键词推广案例,响应式网页设计技术有哪些文章目录 1.回顾上节2. 拷贝构造3. 运算符重载#xff08;非常重要#xff09;4. 赋值运算符重载 1.回顾上节 默认成员函数#xff1a;我们不写#xff0c;编译器自动生成。我们不写#xff0c;编译器不会自动生成 默认生成构造和析构#xff1a;
对于内置类型不做处理对… 文章目录 1.回顾上节2. 拷贝构造3. 运算符重载非常重要4. 赋值运算符重载 1.回顾上节 默认成员函数我们不写编译器自动生成。我们不写编译器不会自动生成 默认生成构造和析构
对于内置类型不做处理对于自定义类型会调用对应的构造/析构。
2. 拷贝构造
#include iostream
using namespace std;
class Date
{
public:Date(int year1, int month1, int day1){_year year;_month month;_day day;}//拷贝构造,函数名和类名相同//拷贝构造的参数为什么不能是传值//C自定义类型的成员在这个地方传值需要调用拷贝构造无穷无尽//因此自定义类型必须调用拷贝构造所以要用引用。最好加constDate(const Date d){_year d._year;_month d._month;_day d._day;}void Print(){cout _year 年 _month 月 _day 日 endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;Date d2(d1);d1.Print();d2.Print();//这时改变_year等会改变d1return 0;
}以下为不调用拷贝构造时会默认生成拷贝构造 内置类型会处理因此日期类不需要自己去写拷贝构造 自定义类型会去调用他的拷贝构造
Stack st1;Stack st2(st1);//栈中保持后进先出后定义的先析构。//st1变成野指针。指向同一块空间的问题
插入删除数据会互相影响析构两次程序崩溃。 默认的拷贝 浅拷贝/值拷贝 **深拷贝**让各自有各自独立的空间开另外的空间把值拷贝下来。 更深入层次的拷贝
typedef int DataType;
class Stack
{
public:Stack(size_t capacity 10){_array (DataType*)malloc(capacity * sizeof(DataType));if (nullptr _array){perror(malloc申请空间失败);exit(-1);}_size 0;_capacity capacity;}
void Push(const DataType data)
{_array[_size] data;_size;
}
Stack(const Stack st)//深拷贝
{_array (DataType*)malloc(sizeof(DataType) * st._capacity);if (nullptr _array){perror(malloc申请空间失败);exit(-1);//直接终止程序}//拷贝数组空间上的值memcpy(_array, st._array, sizeof(DataType) * st._size);_size st._size;_capacity st._capacity;
}
~Stack()
{if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}
}
private:DataType *_array;size_t _size;size_t _capacity;};
int main()
{Stack st1;st1.Push(1);st1.Push(2);st1.Push(3);st1.Push(4);Stack st2(st1);//栈中保持后进先出后定义的先析构。//没有写拷贝构造编译器自动生成了一个return 0;
}什么情况下需要写拷贝构造呢 不能用指针来衡量如果自己实现了析构函数释放了空间就需要实现拷贝构造。
对于内置类型完成浅拷贝/值拷贝–按byte一个个拷贝自定义类型去调用这个成员拷贝构造/赋值重载 2种大方向的特性
typedef int DataType;
class Stack
{
public:Stack(size_t capacity 10){_array (DataType*)malloc(capacity * sizeof(DataType));if (nullptr _array){perror(malloc申请空间失败);exit(-1);}_size 0;_capacity capacity;}
void Push(const DataType data)
{_array[_size] data;_size;
}
Stack(const Stack st)
{//拷贝构造对内置类型完成值拷贝或者浅拷贝。cout Stack(const Stack st) endl;_array (DataType*)malloc(sizeof(DataType) * st._capacity);if (nullptr _array){perror(malloc申请空间失败);exit(-1);//直接终止程序}//拷贝数组空间上的值memcpy(_array, st._array, sizeof(DataType) * st._size);_size st._size;_capacity st._capacity;
}
~Stack()
{if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}
}private:DataType *_array;size_t _size;size_t _capacity;};
//对于自定义类型不需要写拷贝构造和构造。不写编译器会自动生成构造函数构造函数符合我们的需求
class MyQueue
{
public://默认生成构造和析构//默认生成拷贝构造
private:Stack _pushST;Stack _popST;int _size 0;//缺省值用缺省值处理
};
int main()
{Stack st1;st1.Push(1);st1.Push(2);st1.Push(3);st1.Push(4);Stack st2(st1);//栈中保持后进先出后定义的先析构。//没有写拷贝构造编译器自动生成了一个MyQueue q1;//调用了拷贝构造MyQueue q2(q1);return 0;
}那些场景存在拷贝构造 Date d2(d1); Date d3d1;//拷贝构造 传返回值的过程中能用引用就用引用减少拷贝。除非就是想让他自己调用拷贝构造拷贝一份独立的出来 参数基本都可以用引用返回值不一定。局部对象不能用引用。
Date Test(Date d)
{Date temp(d);return temp;
}3. 运算符重载非常重要
为了增强程序的可读性是具有特殊函数名的函数也有其返回值类型函数名字以及参数列表其返回值类型与参数列表与普通的函数类似
比较日期大小 内置类型可以比较大小自定义类型不可以。运算符重载和函数重载无关 函数重载是支持参数名相同参数不同的函数随时可以用 运算符重载自定义类型对象可以使用运算符。 两个地方都用了重载但两个地方没有关联运算符重载:实现一个函数。新增一个关键字operator加操作符有参数有返回值。参数和返回值根据运算符确定。有的有返回值有的没有。运算符有几个操作数就有几个参数
class Date
{
public:Date(int year1, int month1, int day1){_year year;_month month;_day day;}//private:int _year;int _month;int _day;};bool operator(const Date d1, const Date d2)//运算符重载可以实现在全局。
{return d1._year d2._year d1._month d2._month d1._day d2._day;
}
int main()
{Date d1(2023, 9, 14);Date d2(2023, 9, 14);coutoperator(d1, d2)endl;cout ( d1 d2) endl;//全局函数转换成调用这个函数operatord1,d2);和上一行一样//运算符优先级高于return 0;
}当放成私有时
class Date
{
public:Date(int year1, int month1, int day1){_year year;_month month;_day day;}
private:int _year;int _month;int _day;};
直接把函数放在类里面。类外面受到访问限定符的限制放到类里面就解决问题了。但是会报错 其中还有隐藏的参数2个this 成员函数调用的方式也不同了。
//d1d2转换为d1.operator(d2)
bool operator(const Date d){//thisd1;d:d2return this-_year d._year _month d._month _day d._day;}coutd1.operator(d2)endl;cout ( d1 d2) endl;//成员函数转换成调用这个函数d1.operatord2);和上一行一样 运算符重载
函数名operator运算符或操作符返回值类型/参数根据需求调用不能乱接其他符号创造一个新的操作符如operator必须有一个类类型参数**自定义类型**不能对内置类型重载其含义不能改变。如内置类型的整型——不能改变其含义作为类成员函数重载时其形参看起来比操作数目少1因为成员函数的第一个参数为隐藏的this.* :: sizeof ?:三目运算符 .成员访问 注意以上5个运算符不能重载这个经常在笔试选择题中出现
//b1b2小测
bool operator(const Date d)
{if (_year d._year){return true;}else if (_year d._year _month d._month){return true;}else if (_year d._year _month d._month _day d._day){return true;}else{return false;}
}//b1b2复用根据上面有有
bool operator(const Date d)
{return *this d || *this d;
}
//b1b2,取反。
bool operator(const Date d)
{return !(*this d) ;
}
4. 赋值运算符重载
d1d2;//是一种拷贝
//d1d2
void operator(const Date d)//不用引用不会无穷递归但会白白走一次拷贝构造所以最好加上引用
{_year d._year;_month d._month;_day d._day;
}
d3d2d1;//编译不通过d1赋值给d2d2的返回值传给d3连续赋值从右往左赋值。ijk; k赋值给j返回j
Date operator(const Date d)
{_year d._year;_month d._month;_day d._day;//*this是d1return *this;//出了作用域还在应该加引用。//返回值是为了支持连续赋值保持运算符的特性。
}d1d1 自己给自己赋值可以加一个判断
Date operator(const Date d)//引用
{if(this!d)//取地址this是左操作数的地址d是右操作数的别名地址相同则不用自己给自己赋值{_year d._year;_month d._month;_day d._day;}return *this;
}支持连续赋值只要支持连续赋值就都有返回值。。 前置d1.operator(); 后置d2.operator(int); int仅仅是为了占位和牵制重载区分
//d1;
Date Date::operator()
{Date tmp(*this);*this1;return tmp;
}//d1
Date Date::operator(int)
{Date tmp(*this);*this1;return tmp;
}对于内置类型前置和后置没有区别 对于自定义类型**前置**效率高后置还要拷贝