1.拷贝构造函数:
(1)概念和作用:
使用一个已经存在的变量去初始化另一个变量,可以用拷贝构造来完成。
(2)特征:
拷贝构造函数是特殊的成员函数,有以下一些特征:
1.拷贝构造函数是构造函数的一个重载形式。
2.拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。(在cpp中传值引发的复制,也是会调用拷贝构造函数的)。
class Date
{
public:
Date(int year = 2025, int month = 1, int day = 1)
{
_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;
};
class Time
{
public:
Time()
{
_hour = 1;
_minute = 1;
_second = 1;
Time(const Time& t)
{
_hour = t._hour;
_minute = t._minute;
_second = t._second;
cout << "Time::Time(const Time&)" << endl;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 基本类型(内置类型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型
Time _t;
};
int main()
{
Date d1;
// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构
造函数
Date d2(d1);
return 0;
}
注意:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝构造函数完成拷贝的。
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;
};
在主函数里面,stack s2(s1)是会出现大问题的。一者是s2和s1所用的数组的地址是指向同一块空间的,再者是,程序结束时,同一块空间会被释放两次,所以涉及资源申请的时候,拷贝函数是一定需要写的,否则就是浅拷贝。
5.拷贝构造函数经典调用场景总结:
2.赋值运算符重载:
(1)运算符重载:
概念:

class Date
{
public:
Date(int year = 2025, int month = 5, int day = 8)
{
_year = year;
_month = month;
_day = day;
}
//private:
int _year;
int _month;
int _day;
};
bool operator==(const Date& d)
{
return (_year == d._year)&&(_month == d.month)&&(_day == d.day);
}
int main()
{
Dated1(2018, 9, 26);
Dated2(2018, 9, 27);
cout<<(d1==d2)<<endl;
}
这是全局的运算符重载,有了运算符重载之后d1和d2两个对象就可以比较大小了。在平常这个赋值运算符重载是写在类里面的。这样就不需要考虑权限问题。
在上面的d1 == d2就相当于d1.operator(d2)。因为d1作为隐含的参数(this)。
(2)赋值运算符重载:
1.赋值运算符重载格式:
class Date
{
public:
Date(int year = 2025, int month = 5, int day = 8)
{
_year = year;
_month = month;
_day = day;
}
Date(const Date& d)
{
_year = d.year;
_month = d.month;
_day = d.day;
}
Date& operator=(const Date& d)
{
if(this != &d)
{
_year = d.year;
_month = d.month;
_day = d.day;
}
return *this;
}
private:
int _year;
int _month;
int _day;
}
2.赋值运算符只能重载成类的成员函数而不能重载成全局函数。
704

被折叠的 条评论
为什么被折叠?



