这三个函数便于对类实例化的对象进行操作
当一个类被定义时,系统会自动为这个类创建三个公有的成员函数:
构造函数、析构函数、拷贝构造函数
默认下构造函数和析构函数内部为空,拷贝构造函数内部只是简单的值传递
构造函数:主要用于类的对象的初始化
析构函数:主要用于释放空间
拷贝构造函数:主要用于实例化对象时通过另一个对象进行赋值
这三个函数可以用户自定义,但是一旦用户自定义,默认系统创建的就不再调用
1 构造函数的定义和使用
//构造函数与当前类的名字必须一样,并且没有返回值,连void也不能写
//构造函数可以后参数也可以没有,并且构造函数可以函数重载,也可以使用缺省参数
//系统默认就会创建构造函数,但是如果自定义了,系统默认的构造函数将不会调用
//一般建议无参和有参的构造函数都定义,防止只是实例化对象不初始化
class Person
{
public:
Person()
{
cout << "无参构造函数" << endl;
}
Person(int id)
{
cout << "有参构造函数" << endl;
p_ID = id;
}
private:
int p_ID;
};
2 析构函数
析构函数是对成员变量进行释放空间操作,跟类实例化的对象的释放空间没有任何关系
析构函数主要用于成员变量是一个指针变量并且赋值时在堆区开辟空间,使用完毕后会调用析构函数进行释放空间,如果成员变量不涉及指针变量和堆区空间,析构函数就没有用
析构函数主要用于对成员变量进行释放空间,但是析构函数调用时机是有对象决定的
当对象释放空间时,才会调用析构函数
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
//析构函数
//析构函数的函数名与类名一致,没有返回值,连void也不能有,也没有参数,在函数名前需要加~
~Person()
{
cout << "析构函数" << endl;
}
private:
};//s1; //类实例化的全局对象,在main函数执行前调用构造函数,在main执行结束后调用析构函数
//析构函数主要用于对成员变量进行释放空间,如果成员变量没有指针,则析构函数也没有必要去写
//析构函数的调用时机依据对象的释放空间的实际,对象释放空间就会立即调用析构函数
void test1()
{
//栈区开辟的空间会随着当前代码段的结束而释放空间,所以函数结束,对象释放空间,析构函数就会调用
Person p1;
Person p2(1001, "zhangsan", 20, "1999-01-01");
}
void test2()
{
//堆区开辟空间,手动申请手动释放,所以当执行delete时,对象释放空间,就会立即执行析构函数
Person *p1 = new Person();
delete p1;
}
int main(int argc, char *argv[])
{
return 0;
}
3 拷贝构造函数
拷贝构造函数主要用于当实例化对象时另一个对象对其进行赋值时会使用拷贝构造函数
拷贝构造函数如果要自定义,一般也是涉及到成员变量是指针的时候
如果成员变量没有指针,则系统默认的拷贝构造函数就够了,本质就是值传递
如果自己定义了拷贝构造函数,系统默认的拷贝构造函数就不会再调用
//当实例化对象时,使用另一个对象对当前对象进行赋值时才会调用拷贝构造函数
Person p2 = p1;
//注意:此时一定不会调用拷贝构造函数,使用的是运算符重载
Person p3;
p3 = p1;
//**其他地方调用拷贝构造函数**
//方法1:当给函数传参时会调用拷贝构造函数
void myfun1(Person p)
{
}
//注意:如果参数是引用,由于没有开辟新的空间,所以不会调用拷贝构造函数
void myfun2(Person &p)
{
}
//方法2:当函数返回时也会调用拷贝构造函数
Person myfun3()
{
static Person p = Person(1002, "lisi", 20, "2000-09-09");
return p;
}
//附加:返回的是引用,调用时通过引用接收返回值,此时没有开辟新的空间,也就没有调用拷贝构造函数
Person& myfun4()
{
static Person p = Person(1002, "lisi", 20, "2000-09-09");
return p;
}
3 涉及成员变量是指针的时候三个函数的使用
#include <iostream>
#include <string.h>
using namespace std;
class Person
{
public:
//构造函数
Person()
{
cout << "无参构造函数" << endl;
}
Person(int id, char *name)
{
cout << "有参构造函数" << endl;
p_ID = id;
//需要先开辟空间然后再赋值
p_Name = new char[strlen(name) + 1];
strcpy(p_Name, name);
}
//析构函数
~Person()
{
cout << "析构函数" << endl;
if(p_Name != NULL)
{
delete []p_Name;
p_Name = NULL;
}
}
//拷贝构造函数
Person(const Person &ob)
{
cout << "拷贝构造函数" << endl;
p_ID = ob.p_ID;
//由于调用拷贝构造函数的时候没有调用有参构造函数,所以也需要先开辟空间
p_Name = new char[strlen(ob.p_Name) + 1];
strcpy(p_Name, ob.p_Name);
}
void getMsg()
{
cout << p_ID << "-" << p_Name << endl;
}
private:
int p_ID;
char *p_Name;
};
void test1()
{
Person p1 = Person(1001, "zhangsan");
p1.getMsg();
Person p2 = p1;
p2.getMsg();
}
int main(int argc, char *argv[])
{
test1();
return 0;
}