一.构造
1.构造的作用
看如下代码:
class text {
private:
int x, y;
public:
void set_xy(int x, int y) {
this->x = x;
this->y = y;
}
};
int main(int argc, char** argv) {
text t1;
//如果没有构造函数,在这两句之间t1可能会被其他线程调用,产生不安全现象。
t1.set_xy(1, 2);
}
因此,构造作用:在对象被创造的时候,用来初始化,防止不安全。
2.构造的定义
构造函数没返回值。
看如下代码:
class Text {
private:
int x, y;
public:
//构造函数,其函数名与类名相同,没有返回值。
//方法一:
Text(int x, int y) {
this->x = x;
this->y = y;
}
//方法二:
Text(int x, int y) :x(x),y(y){}
};
int main(int argc, char** argv) {
//调用构造函数,可以有效防止t1被其他函数调用,产生不安全现象
//作用:在对象被创造的时候,用来初始化
Text t1(1,2);
}
可以看到逐语句调试:
3.构造的重载
普通重载、无参构造函数
class Text {
private:
int x, y;
public:
Text(int x, int y) {
this->x = x;
this->y = y;
}
Text() {//重载,无参的构造函数
x = 0;
y = 0;
}
Text(int x) {//重载
this->x = x;
y = 0;//最好此处对y初始化,当然不初始化也可以。
}
};
int main(int argc, char** argv) {
Text t2;//调用无参的构造函数,注意不是Text t2();
}
二.析构
析构函数没有返回值。
析构函数没有形参。
在一个对象临死之前,自动调用析构函数。
析构函数调用的顺序,跟析构函数相反,谁先构造,谁后析构。
class Text {
private:
int x, y;
public:
//构造函数,没有返回值
Text(int x, int y) {
this->x = x;
this->y = y;
}
//析构函数,没有返回值;没有形参;在一个对象临死之前,自动调用析构函数;
~Text() {
cout << "x=" << x << ",y=" << y << endl;
}
};
int main(int argc, char** argv) {
Text t2(1,2);
}
结果:
可以看到这里没有调用析构函数。但是还是输出cout中内容。
三.默认的构造函数和析构函数
class Text {
private:
int x, y;
public:
//以下注释,为默认构造函数和析构函数。在不写时,系统默认如下。
/*Text() {
}
~Text() {
}*/
void get_xy() {
cout << "x=" << x << ",y=" << y << endl;
}
};
int main(int argc, char** argv) {
Text t1;//默认的构造函数,其值当然为乱码。
t1.get_xy();
}
四.拷贝构造函数
参数最好使用引用型
复制构造函数的参数为什么一定要用引用传递,而不能用值传递?
【解】值传递的参数在参数传递时有一个构造过程,即用实际参数的值构造形式参数,这个构造过程是由复制构造函数完成的。如果将复制构造函数的参数设计成值传递,会引起复制构造函数的递归调用。
class Text {
private:
int x, y;
public:
Text(int x, int y) {
this->x = x;
this->y = y;
}
~Text() {
cout << "x=" << x << ",y=" << y << endl;
}
//拷贝函数,类似于构造函数。这里加const和&是为了保护原有的数据不被改变。
Text(const Text& another) {
cout << "调用拷贝函数" << endl;
x = another.x;
y = another.y;
}
};
int main(int argc, char** argv) {
Text t1(0,1);
Text t2(t1);//拷贝函数,将t1值赋给t2。
}
结果:
注意:调用拷贝函数是在初始化时候调用,如果用t2=t1,则是使用赋值操作函数。
五.类中默认函数的隐藏条件
1.类中会有个默认的无参构造函数:
当没有任何显示的构造函数(显示的无参构造、显示有参构造、显示拷贝构造)的时候,默认无参构造就无法使用。
例子:如下代码有拷贝函数,看报错。
class Text {
private:
int x, y;
public:
//拷贝函数
Text(const Text& another) {
cout << "调用拷贝函数" << endl;
x = another.x;
y = another.y;
}
};
int main(int argc, char** argv) {
Text t1;
}
错误:
2.会有默认的拷贝函数。
3.会有默认的析构函数。