构造函数
构造函数进行初始化
构造函数,它是一种特殊的函数,主要用来在创建对象时初始化对象,即为对象的成员变量赋初始值。
也可以将对象在创建之初需要执行的逻辑写在构造函数中。
构造函数的特殊性:
- 没有(不是缺省)函数返回值类型
- 函数名和类名相同
- 对象存在时会自动调用构造函数,刚好可以帮助完成初始化的功能
- 构造函数的调用时机:一个栈区对象产生,一个指针动态一个堆区内存对象产生
- 构造函数可以重载,在调用时根据实际调用时给的参数来决定执行哪一个构造函数。构造函数在对象创建时,调用是唯一的。
- 构造在没有主动书写的情况下,系统会提供一个隐式的什么都不干的默认构造函数。
代码示例
#include<iostream>
class MyStu
{
private:
int id;
int age;
public:
MyStu() //构造函数
{
id = 0;
age = 123;
setStuID(id); //函数体内可以再次调用函数
}
MyStu(int i, int a)
{
id = i;
age = a;
}
void setStuID(int i)
{
id = i;
}
int getStuID()
{
return id;
}
int getStuAge()
{
return age;
}
};
void main()
{
MyStu m(208, 18); // 对象产生,栈区的对象产生 -- 会触发构造函数
printf("m 的id=%d, age=%d\n", m.getStuID(), m.getStuAge());
MyStu *pm; //这个不是对象,叫对象指针
pm = new MyStu(209, 20); //这个也是对象,堆区的无名对象产生 -- 会触发构造函数
printf("pm 的id=%d, age=%d\n", pm->getStuID(), pm->getStuAge());
MyStu m1[10]; //对象数组。数组中在初始化每一个元素时会调用默认无参构造
}
运行结果
拷贝构造函数
拷贝构造函数也是构造函数,是一种特殊的构造函数。
拷贝构造调用时机:
- 主动调用拷贝构造
- 函数的实参到形参是拷贝,这时会调用拷贝构造
- 函数的返回值时,也是拷贝构造
没有写拷贝构造,系统会提供一个隐式的拷贝构造,该拷贝构造函数会把参数的数据全部拷贝一份到自己身上。
代码示例:
#include<string.h>
class MyStu
{
private:
int id;
int age;
char*name;
public:
MyStu()
{
id = 0;
age = 0;
}
MyStu(MyStu const &other) //拷贝构造的写法
{
id = other.id;
age = other.age;
if (other.name)
{
name = new char[strlen(other.name) + 1];
strcpy(name, other.name);
}
}
void setStuId(int i)
{
id = i;
}
void setStuName(char *n)
{
name = new char[strlen(n)+1];
strcpy(name, n);
}
~MyStu()
{
if (name != NULL)
{
delete []name;
name = NULL;
}
}
};
void main()
{
int a = 10; //变量的初始化赋值(在C++里面可以理解为整数a的拷贝构造)
MyStu m;
m.setStuId(101);
m.setStuName("li si");
MyStu m1(m); //拷贝构造的显式调用
MyStu m2 = m; //拷贝构造的隐式调用
}
当我们注释自定义的拷贝构造函数时,运行程序,会报错:
原因如下图所示:
即默认的拷贝叫浅拷贝,只拷贝类对象的内存数据。所以,对象中有堆内存,必须重写构造函数,来实现深拷贝。深拷贝就是把对象中的堆内存、对象内存、逻辑内存都拷贝过来。
析构函数
析构函数和构造函数一样,也是一种特殊的函数。
主要的作用是在对象生命周期结束时,做一些清理工作,也可以将对象生命周期最后要做的事情写在析构函数中。
析构函数的调用时机:
- 栈区对象出作用域死亡时调用。
- 主动通过delete函数去释放掉堆区的无名对象时调用。
当对象中会存在堆区数据,必须写析构函数,且在析构函数中去主动释放堆区数据。
代码示例
class MyStu
{
int id;
int age;
char *name; //堆区数据
public:
~MyStu() //析构函数
{
if (name != NULL)
{
delete[]name;
name = NULL;
}
}
};
this指针
- this指针是系统自动生成,且隐藏,我们看不到定义,但是可以使用。
- this指针并不是对象本身的一部分,它的作用域在类的内部。当类的普通函数在访问类的普通成员的时候,该this指针总是指向调用者对象。
观察如下代码,id=id出现了同名,运行时会导致代码出错。
将id = id改为 this->id = id即可
this->id = id;
this指针指向调用者对象的首地址。
this指针的使用:
- 在类中使用,不能在类外使用。
- this->类中成员数据;this->类中成员函数;通过this指针找到调用者对象的某个成员。
- return this:表示在类中返回该调用者对象的首地址。
- return *this:表示在类中返回该调用者对象。
类的分文件编写(类的标准写法)
可通过VS软件快速创建类的分文件:
这时会看到有两个文件生成:class_one.h、class_one.cpp,class_one.h主要用来声明和定义函数,不写有内存的数据,class_one.cpp中写带内存的数据。