类与对象(中—-拷贝构造函数)
1、概念
概念:只有单个形参,该形参是对 本类类型对象的引用(一般用const修饰),在用 已存在的类类型对象创建新对象时,由编译器自动调用。
2、特征
// 拷贝构造函数也是特殊的成员函数,其特征如下:
//(1)拷贝构造函数是构造函数的一个 重载形式。
//(2)拷贝构造函数的 参数只有一个且必须是类类型对象的引用。(若形参使用传值方式调用,编译器会直接报错或者引发无穷递归)
// 拷贝构造————传值————拷贝构造(造成无穷递归)
class Date
{
public:
//全缺省构造函数
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
//拷贝构造函数
// Date d2(d1); 拷贝构造(用 d1初始化d2,所以要先将d1传过去)
Date(const Date& d)
{
cout<< "Date(Date& d)" << endl;
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
void Func()
{
Date d1(2023,8,2);
Date d2(d1); //拷贝构造(用 d1初始化d2,所以要先将d1传过去)
Date d3 = d1; //也是拷贝构造(另一种形式,为了兼容C语言的语法)
}
int main()
{
Func();
return 0;
}
3、拷贝构造的场景
// 1 3 2 6 7 要打印一下路径值path,但是打印完之后数据就丢了,所以要先拷贝构造一下path
// Stack path;
// Stack copy(path);
// while (!copy.Empty()) //用拷贝构造的栈去打印数字,不会影响原来的path
// {
// cout<< copy.Top() <<endl;
// copy.Pop();
// }
4、我们不写时,自动生成的默认拷贝构造函数
//若未显示定义,编译器会生成默认的拷贝构造函数。
//注意:在编译器生成的默认拷贝构造函数中,内置类型成员变量是按照 字节方式 直接拷贝的(值拷贝\浅拷贝),而自定义类型成员变量 是调用其拷贝构造函数完成拷贝的。
4.1 日期类
class Date
{
public:
//全缺省构造函数
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
//默认拷贝构造函数
/*Date(const Date& d)
{
cout<< "Date(Date& d)" << endl;
_year = d._year;
_month = d._month;
_day = d._day;
}*/
private:
int _year;
int _month;
int _day;
};
void Func()
{
Date d1(2023,8,2);
Date d2(d1); //拷贝构造(用 d1初始化d2,所以要先将d1传过去)
}
int main()
{
Func();
return 0;
}
4.2 My Queue类
//Stack类
typedef int DataType;
class Stack
{
public:
//构造函数
Stack(int capacity = 3)
{
_array = (DataType*)malloc(sizeof(DataType) * capacity);
assert(_array);
_capacity = capacity;
_size = 0;
}
//析构函数
~Stack()
{
free(_array);
_array = nullptr;
_capacity = _size = 0;
}
//默认拷贝构造函数发挥作用
//Stack st1;
//Stack st2(st1);
//这儿 st2是借助默认拷贝构造st1的(值\浅拷贝【相当于memcpy】的方式),所以st2内的 DataType* _array 与 st1内的指针指向同一块儿空间。
// 浅拷贝的两个缺陷:{如何解决:自己实现深拷贝(后面讲解)}
// (1)一个对象修改会影响另一个对象。
// (2)会析构两次,程序崩溃。
private:
DataType* _array;
int _capacity;
int _size;
};
//MyQueue类
class MyQueue
{
public:
void push(int x) {}
//...
//默认拷贝构造函数
// MyQueue q1;
// MyQueue q2(q1);
// MyQueue采取默认拷贝构造的方式,其成员变量Stack可以调用它自身的拷贝构造函数实现。(MyQueue采取默认拷贝构造需要建立在 其成员变量Stack具有拷贝构造函数 的基础上)
private:
Stack _st1;
Stack _st2;
};
void Func()
{
Stack st1;
Stack st2(st1);
MyQueue q1;
MyQueue q2(q1);
}
int main()
{
Func();
return 0;
}