构造函数是干嘛用的
构造函数是对象在被创建的时候,由编译器自动调用并且分配内存空间的函数(不管你写不写它都会有),作用是初始化对象的成员。
构造函数的种类
1、默认构造函数
语法:类名(){}
每一个类都自带一个默认构造函数,函数内为空,如果你写了默认构造函数,则运行时编译器将会调用你写的默认构造函数。
2、有参构造函数
语法:类名(参数1,参数2…){}
有参构造有两种初始化方式,一是赋值法,二是初始化列表,赋值法通俗易懂,初始化列表是通过 **类名(参数1,参数2…):成员1(参数1),成员2(参数2)…{}**来实现的。推荐使用第二种方法,虽然两种方法运行效率差不多,但是二者有本质的区别,法一的成员变量是被赋值了而不是初始化,法二发生的时间更早,发生在成员的default构造函数被自动调用之时。
3、拷贝构造函数
语法:类名((const)类名 &变量){}
顾名思义,拷贝构造函数就是将一个对象的所有成员拷贝到新的对象上,其实编译器也提供拷贝构造函数,通过编译器自带的拷贝构造函数进行拷贝的方法被称为浅拷贝,这样的拷贝是逐字节的拷贝,即二者一模一样,但是存在一个问题,如果我们创建一个指针并在堆区开辟内存,在拷贝完成之后根据顺序会先调用被拷贝对象的析构函数来delete这个内存,然后拷贝对象再调用析构函数释放内存,但由于二者的指针指向同一片内存区域,所以会存在重复释放的问题,故需要自行创建拷贝函数,这样称为深拷贝,深拷贝并不是简单的复制粘贴,而是另外开辟一片内存空间,这就避免重复释放。
注意 如果写了有参构造函数和拷贝构造函数那么编译器将不再提供默认构造函数,如果需要使用,需要你自己写。
贴个代码
#include <iostream>
using namespace std;
class Person{
public:
Person(){
cout<<"构造函数调用"<<endl;
}
Person(int a){
age=a;
cout<<"有参构造函数"<<endl;
// cout<<age<<endl;
}
Person(const Person &p){
age=p.age;
cout<<"拷贝构造函数"<<endl;
// cout<<age<<endl;
}
~Person(){
cout<<"析构函数调用"<<endl;
}
int age;
};
void test01(){
//括号法
Person p9;
Person p8(10);
Person p7(p8);
//显示法
Person p1;
Person p2=Person(10);
Person p3=Person(p2);
//隐式转换法
Person p4=10;
Person p5=p4;
}
int main()
{
test01();
}
再贴个
#include <iostream>
using namespace std;
class Person{
public:
Person(){
cout<<"Person默认构造函数调用"<<endl;
}
Person(int age,int height){
m_age=age;
m_height=new int(height);//创建堆区数据的语法,应该用指针去接收
cout<<"Person有参构造函数调用"<<endl;
}
~Person(){
if(m_height!=NULL){
delete m_height;
}
cout<<"Person析构函数调用"<<endl;
}
Person(const Person &p){
m_age=p.m_age;
m_height=new int(*p.m_height);
cout<<"Person拷贝构造函数调用"<<endl;
}
int m_age;
int *m_height;
};
void test01(){
Person p1(18,160);
cout<<p1.m_age<<" "<<p1.m_height<<endl;
Person p2(p1);
cout<<p2.m_age<<" "<<p2.m_height<<endl;
}
int main(){
test01();
}