类的6个默认构造函数
如果一个类是空类,那么编译器会默认生成6个构造函数,这六个构造函数
1)初始化和清理两个:构造函数和析构函数
2)拷贝复制:拷贝构造和赋值重载
3)取地址重载:主要是普通对象和const对象取地址(很少自己实现)此处为两个
构造函数
构造函数:就相当于一台机床(种类单一的),只要给出相应的属性就可以造出相应的对象。
它是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次。(机床可能不太得当,有些机床也也可加工多次,此处领悟意思即可)。
且构造函数是特殊的成员函数,主要任务是初始化对象,并不是开辟空间。
特征:
1)函数名与函数相同
2)无返回值
3)对象实例化的时候编译器自动调用的函数
4)构造函数可以重载(给不同的值,制造不同的对象)
5)如果没有显式的定义构造函数,编译器会默认的自动生成,定义了则不生成
析构函数
析构函数:相当于垃圾处理厂的地方,东西不用了就扔了,垃圾车(编译器)再送到垃圾处理厂。
与构造函数相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的,在对象销毁的时候自动调用。
特性:
1)析构函数是在类名前加作用符~
2)无参数,无返回值(注意不能重载)
3)对象生命周期,自动调用
class Date {
public:
Date(int year = 100)
:_year(year) //如果不写这一句话开始在里面放的随机值,在下面的语句中在赋值,写了就一步到位
{
_year=year;
cout << "constructor" << endl;
}
int _year;
~Date() { //析构函数
cout << "destructor" << endl ;
}
};
void test(){
Date A(1);
Data b;
cout << A._year << endl;
}
int main() {
system("pause");
return 0;
}
运行结果如下
拷贝构造函数
如果像创建一个和原来对象一模一样的对象,就需要用到拷贝构造函数;
特征:
1)只有一个形参,该形参是对本类类型对象的引用(一般是const的引用放止被修改),如果用户自己已经实现,那么编译器会在拷贝创建对象的时候自动调用,不然就会自动生成默认的(浅拷贝)。
2)拷贝构造函数,是构造函数的一个重载
3)传值的方式必须是引用传参,如果是形参传参,因为在创建形参的时候又会调用拷贝构造函数,然后发生无穷的递归调用。
4)如果不涉及到资源管理(对象中有开辟空间的),则必须自己实现拷贝构造函数,防止浅拷贝,资源释放多次。
例如在上述代码中加入此段
public:
Date(const Date& d) {
_sun = 31;
_year = d._year;
}
int sun;
运算符重载
运算符进行重载之后,使之成为了特殊名称的函数,改运算符就成了一个函数名,也具有返回值的类型,函数名,以及参数列表,返回值类型与普通的函数换回值类似。
关键字 operator
函数原型 : 函数原型 operator 操作符(参数列表);
注意事项:
1)重载操作符必须有一个类类型或者枚举类型的操作数
2)用于内置类型的操作符,其含义不能改变
3)作为类成员的重载函数是,其形参看起来比操作数数目少1,因为成员函数有一个默认的新参this,在此次被限定为第一个形参
4) (* ) (::) (zieof) (?) (.) 五个运算符不能重载
例如如下代码
void test1() {
Date a(2);
Date b(3);
Date c;
c = a + b;
cout <<c._year<< endl;
}
编译器会直接报错 说没有与“+”匹配的操作数,此时如果在代码中加入
public:
Date operator+(const Date& b) {
return _year + b._year;
}
在返回值的时候,创建了形参所以多调用了构造和析构函数;
赋值运算符的重载
赋值运算符重载其实就是在类中重载“=” ,
主要注意以下四点:
1.返回值可以使用 类类型的引用,因为引用不会创建临时对象速度快
2.参数类型(const Date& )防止被修改
3.返回 *this
4.如果没有显示定义那么就会自动生成,浅拷贝
例如如下代码:
Date& operator=(const Date&b) {
_year = b._year;
return *this;
}
const成员
将const修饰的成员称之为const成员,实际上是修饰了该成员函数隐藏的this指针,表面当前对象的内容不允许被修改
两种写法就对该类而言 const Data A; void fun()const{};
对于第一种表示对象是const类型的对象,第二种表示该函数是const类型的函数。具体意思如下:
例如如下代码:
在类种加入如下
public:
void print1() {
cout << "非const" << endl;
}
void print2()const {
cout << "const" << endl;
}
测试函数
void test2() {
Date A;
const Date B;
A.print1();
A.print2();
B.print1();//该句报错
B.print2();
}
此时编译会报错,说const类型的成员调用了非const类型的成员函数。
去掉此句编译通过
取地址和const取地址操作符的重载
书写的方法和上面类似:
pubilc:
Date* operator&()
{
return *this;
}
Date* operator&() const
{
return *this;
}
改运算符一般不需要重载,用默认生成的即可。除非想获取别的内容。