实力网站开发,建站公司网站源码社区,软件设计的过程,昆明网站排名优化费用目录
一. 拷贝构造函数
1. 引入
2. 拷贝构造的概念
3. 浅拷贝
4. 深拷贝
二. C运算符重载
1. 概念
2. 注意事项
3.举例 一. 拷贝构造函数
1. 引入
我们在创建对象时#xff0c;能不能创建一个与原先对象一模一样的新对象呢#xff1f;为了解决这个问题#x…目录
一. 拷贝构造函数
1. 引入
2. 拷贝构造的概念
3. 浅拷贝
4. 深拷贝
二. C运算符重载
1. 概念
2. 注意事项
3.举例 一. 拷贝构造函数
1. 引入
我们在创建对象时能不能创建一个与原先对象一模一样的新对象呢为了解决这个问题C提出了拷贝构造的概念。 2. 拷贝构造的概念
当我们想把一个对象赋值给另一个对象或者创建一个与已存在对象一某一样的新对象时需要调用它的拷贝函数来进行复制。我们以下面的代码举例
#includeiostream
using namespace std;class Date
{
public:Date(int year 2024, int month 3, int day 14){_year year;_month month;_day day;}// Date(const Date d) // 错误写法编译报错会引发无穷递归Date(const Date d)//拷贝构造函数{_year d._year;_month d._month;_day d._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2(d1);
//这样写也可以Date d2 d1;return 0;
}
拷贝构造函数也是特殊的成员函数其特征如下
1. 拷贝构造函数是构造函数的一个重载形式。
2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用使用传值方式编译器直接报错 因为会引发无穷递归调用。
为什么会引发无穷递归呢是因为如果我们传值当形参的话那么形参是实参的一份临时拷贝又会拷贝构造函数这样就会无限递归下去。
所以我们在书写构造函数的时候一定要使用传引用当做形参。 3. 浅拷贝
我们知道C语言函数在传递参数时会将实参的值传递给形参中间自动存在一个变量的临时拷贝过程那如果我们不写拷贝构造函数编译器会发生什么情况呢 我们发现仍然完成了值拷贝。这是因为拷贝构造函数没有显示定义的化编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝这种拷贝叫做浅拷贝或者值拷贝。需要注意的是在编译器生成的默认拷贝构造函数中内置类型是按照字节方式直接拷贝的而自定义类型是调用其拷贝构造函数完成拷贝的。
4. 深拷贝
编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了还需要自己显式实现吗我们来看下面的代码
typedef int DataType;
class Stack
{
public:Stack(size_t capacity 10){_array (DataType*)malloc(capacity * sizeof(DataType));if (nullptr _array){perror(malloc申请空间失败);return;}_size 0;_capacity capacity;}void Push(const DataType data){// CheckCapacity();_array[_size] data;_size;}~Stack(){if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}
这里刚开始创建了一个S1 对象又创建了一个S2 对象去进行调用拷贝构造函数进行拷贝而这里只进行了浅拷贝在 S2 进行拷贝构造的时候只是简单的把值复制过去了所以 S2 和 S1 是指向同一块空间并没有给 S2 去单独开辟一个一模一样的空间。那为什么程序回出现崩溃呢 S2 和 S1 指向用一块空间而当程序结束的时候 S2 调用它的析构函数去吧 S1 所指向的空间给释放了, 那么当 S1 在释放的时候就重复释放了原来释放的空间导致程序崩溃。一块空间不能被释放两次。 因此我们我们需要进行深拷贝
#includeiostream
#includestdlib.h
using namespace std;class Stack
{
public:Stack(size_t capacity 10){_array (int*)malloc(capacity * sizeof(int));if (nullptr _array){perror(malloc申请空间失败);return;}_size 0;_capacity capacity;}Stack(const Stack p1){int* tmp (int*)malloc(sizeof(int) * p1._capacity);if (tmp nullptr){perror(file malloc);exit(-1); }memcpy(tmp, p1._array, sizeof(int) * p1._size);_array tmp;_capacity p1._capacity;_size p1._size;}void Push(const int data){// CheckCapacity();_array[_size] data;_size;}~Stack(){if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}}
private:int* _array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}所以我们需要动态申请空间显示定义拷贝构造函数把空间大小和值内容拷贝进去。
因此我们有以下总结
类中如果没有涉及资源申请时拷贝构造函数是否写都可以一旦涉及到资源申请 时则拷贝构造函数是一定要写的否则就是浅拷贝。拷贝构造函数典型调用场景使用已存在对象创建新对象 函数参数类型为类类型对象 函数返回值类型为类类型对象。
二. C运算符重载
1. 概念
C为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数也具有其 返回值类型函数名字以及参数列表其返回值类型与参数列表与普通的函数类似。 函数名字为关键字operator后面接需要重载的运算符符号。
函数原型返回值类型 operator操作符(参数列表)
2. 注意事项 不能通过连接其他符号来创建新的操作符比如operator
重载操作符必须有一个类类型参数 用于内置类型的运算符其含义不能改变例如内置的整型不能改变其含义
作为类成员函数重载时其形参看起来比操作数数目少1因为成员函数的第一个参数为隐藏的this
以上下个运算符不能重载 3.举例
class Date
{
public:Date(int year 1900, int month 1, int day 1){_year year;_month month;_day day;}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(2024, 3, 14);Date d2(2024, 3, 15);cout (d1 d2) endl;return 0;
}