构造和析构函数
构造函数:完成对象初始化工作
析构函数:完成对象清理工作
(1)构造函数语法:
1)函数名和类名同
2)函数的参数可以不同,可以重载
3)程序在调用对象的时候会自动构造,无须手动调用,而且只会调用一次
4)构造函数没有返回值也不写void
(2)析构函数语法:
1)析构函数,没有返回值,也不写void
2)函数名称和类名相同,在前面加~
3)析构函数不可以有参数,因此不可以发生重载
4)程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次
注意:先创建的对象后清理
例子:
#include<iostream>
using namespace std;
class test
{
private:
int number;
public:
test(int number)
{
this->number=number;
cout<<"number="<<number<<endl;
}
~test()
{
cout<<"析构成功"<<this->number<<endl;
}
};
void test()
{
class test t(1);
class test t1(2);
}
int main()
{
test();
}
打印结果:number=1
number=2
析构成功2
析构成功1
构造函数的两种分类:
1)按有无参数分:有参构造和无参构造
2)按类型分:普通构造和拷贝构造
三种调用方式:
1)括号法
2)显式法
3)隐式转换法
#include<iostream>
using namespace std;
class person
{
public:
person(const person &p)//拷贝构造函数
{
this->age=p.age;
this->sex=p.sex;
}
person(int age,int sex)
{
this->age=age;
this->sex=sex;
}
void get_age_sex()
{
cout<<age<<endl;
cout<<sex<<endl;
}
person()
{
}
private:
int age;
int sex;
};
void test()//调用
{
//1.括号法
person p;//调用默认构造函数时,不要加(),不然编译器会认为在声明一个函数
person p1(10,2);
person p2(p1);
p2.get_age_sex();
//显示法
person x_p;
person x_p1=person(10,2);
person x_p2=person(x_p1);
//person(10,2)匿名对象,特点:当前行执行结束后,系统会立即回收匿名对象
//不要利用拷贝构造函数来初始化匿名对象;编译器会认为person(x_p1)==person x_p1,编译器会认为是一个对象的声明
//隐式转换法
person y_p={10,2};
person y_p1=y_p;
//构造函数有多个参数的时候使用{}
}
int main()
{
test();
}
构造函数的使用场景:
1)用已经创建好的对象为另一个对象赋值
2)一个对象在函数中作为形参,且该函数被调用
3)函数中创建的局部对象变量作为返回值为其他对象赋值(编译器不同,可能会优化处理)
#include<iostream>
using namespace std;
class person
{
public:
person()
{
cout<<"默认构造"<<endl;
}
person(int age)
{
this->age=age;
cout<<"赋值构造"<<endl;
}
~person()
{
cout<<"析构函数"<<endl;
cout<<"age="<<age<<endl;
}
person(const person &p)
{
cout<<"拷贝构造"<<endl;
}
int age;
};
void test_one()
{
//使用已经创建完成的对象来初始化另一个对象
person one_p(20);
person one_p1(one_p); //person one_p1=person(one_p);person one_p1=one_p;
}
#define thiree//如果定义了thiree那么就验证 test_thiree
person test_two
(
#ifndef thiree
person two_p//以值传递的方式给函数参数传值
#endif
)
{
#ifdef thiree
person two_p1(20);
cout<<"two"<<endl;
return two_p1;
#endif
}
//值返回方式返回局部对象(这里在黑马上说VS使用了拷贝构造,在VScode和Linux虚拟机上使用g++实验出来的结果好像没有使用拷贝构造函数)
//实际上按道理来说是tes_two()中创建了一个局部的对象two_p1,然后将two_p1赋值给thiree_p;按道理来讲是调用了一次赋值构造,一次拷贝构造,2次析构。这里只看到赋值构造和析构分别为一次,应该是编译的问题
//编译器好像优化处理了,让我们只看到初始化赋值,和一个析构,中间应该会有拷贝和其他析构。
person test_thiree()
{
person thiree_p=test_two();
cout<<"thiree"<<endl;
++thiree_p.age;
return thiree_p;
}
void test_fuor()
{
person four_p=test_thiree();
cout<<"four"<<endl;
}
int main()
{
// test_one();
#ifndef thiree
person p;
test_two(p);
#endif
//test_thiree();
test_fuor();
}
C++会提供一个默认的:构造函数,拷贝构造函数(值拷贝,拷贝所有属性),析构函数
1)如果我们定义了构造函数,它就不会提供默认的构造函数了,其他的仍然提供。
2)如果我们定义了拷贝构造函数,他就不会提供默认的拷贝构造函数了,其他的仍然提供。