构造函数与析构函数
构造函数
1、什么构造函数
类、结构、联合中的特殊成员函数,与类名、结构名、联合名同的成员函数,没有返回值。
class 类名
{
public:
类名(参数列表)
{
}
};
2、何时调用构造函数
当创建类对象时(实例化对象)会自动调用构造函数。
int main(int argc,const char* argv[])
{
// 调用无参构造
Student stu;
Student* stup = new Student;
// 调用有参构造
Student stu1(10010,"hehe",'w',18,98);
Student* stup1 = new Student(10011,"xixi",'m',20,95);
// 调用有参构造,c11语法标准才支持,-std=c++11
Student stu2 = {10010,"hehe",'w',18,98};
return 0;
}
3、在构造函数中应该做什么
构造函数负责创建使用对象的环境,一般构造函数中负责:
1、给成员变量初始化
2、给指针成员分配内存
3、从文件、网络、数据库加载数据
4、完成一些准备工作
4、实现构造函数要注意的问题
在创建类对象时,一定会调用构造函数,如果类中没有显式实现构造函数,编译器会自动生成一个无参的什么都不做的构造函数。
如果显式实现了有参构造函数,那么编译器就不会再生成无参构造。
注意:在使用new[] 创建n个对象时,无法保证给所有的类对象都单独提供参数,去调用有参构造,那么必然需要调用无参构造,此时如果没有显式实现无参构造,编译就会出错。
方法1:
class Student
{
public:
Student() {} // 极简无参构造
};
方法2:
给有参构造函数的所有成员都设置默认形参,当需要调用无参构造时,会自动使用默认参数调用有参构造。
// 无参构造未必无参
class Student
{
...
public:
Student(int _id=0,const string& _name="",char _sex='w',short _age=0,float _score=0)
{
id = _id;
name = _name;
sex = _sex;
age = _age;
score = _score;
cout << "我是有参构造" << endl;
}
};
5、explicit关键字的作用
如果类中有单参的构造函数,那么它的参数类型数据就能隐藏提升为类对象,如果不使用该功能,可以在单参构造函数的前面加 explicit 关键字,参数类型数据就不能再隐藏提升为类对象。
总结:explicit关键字的作用就是禁止单参构造函数的类型提升功能。
#include <iostream>
using namespace std;
class Test
{
int num;
public:
[explicit] Test(int _num)
{
num = _num;
}
};
void func(Test t)
{
cout << "我被调用了" << endl;
}
int main(int argc,const char* argv[])
{
func(1234);
}
析构函数:
1、什么析构函数
类、结构、联合中的特殊成员函数,在类名、结构名、联合的前面加~,就是析构函数,没有返回也没有参数。
struct Student
{
int id;
string name;
char sex;
short age;
float score;
public:
Student(void)
{
cout << "我是无参构造函数" << endl;
}
Student(int _id,const string& _name,char _sex,short _age,float _score)
{
id = _id;
name = _name;
sex = _sex;
age = _age;
score = _score;
cout << "我是有参构造" << endl;
}
~Student(void)
{
cout << "我是析构函数" << endl;
}
};
2、在析构函数中应该做什么
析构函数负责对象销毁时的收尾工作,一般构造函数中负责:
1、释放指针成员指向的堆内存
2、往文件中、数据库保存数据
3、何时调用析构函数
1、当类对象离开它所在的作用域时,系统会自动销毁类对象,并自动调用析构函数。
#include <iostream>
using namespace std;
struct Student
{
int id;
string name;
char sex;
short age;
float score;
public:
Student(void)
{
cout << "我是无参构造函数" << endl;
}
Student(int _id,const string& _name,char _sex,short _age,float _score)
{
id = _id;
name = _name;
sex = _sex;
age = _age;
score = _score;
cout << "我是有参构造" << endl;
}
~Student(void)
{
cout << "我是析构函数" << endl;
}
};
int main(int argc,const char* argv[])
{
do{
// 当创建类对象时,自动调用构造函数,当对象离开它的作用域时,会自动调用析构函数
Student stu;
}while(0);
cout << "-----------" << endl;
}
2、当使用delete或delete[] 释放堆内存上的类对象时,会自动调用析构函数(必须使用delete释放)。
#include <iostream>
using namespace std;
struct Student
{
int id;
string name;
char sex;
short age;
float score;
public:
Student(void)
{
cout << "我是无参构造函数" << endl;
}
Student(int _id,const string& _name,char _sex,short _age,float _score)
{
id = _id;
name = _name;
sex = _sex;
age = _age;
score = _score;
cout << "我是有参构造" << endl;
}
~Student(void)
{
cout << "我是析构函数" << endl;
}
};
int main(int argc,const char* argv[])
{
// 使用new 或 new[] 在堆内存上创建类对象时会自动调用构造函数
Student* stup = new Student;
Student* stus = new Student[10];
// 类对象的个数,也是执行构造、析构函数的次数
cout << *((int*)stus-1) << endl;
// 使用delete 或 delete[] 释放堆内存上的类对象时会自动调用析构函数
delete stup;
delete[] stus;
// 注意:使用new创建的就使用delete释放,使用new[]创建的就使用delete[]释放,不能混用
return 0;
}
4、析构函数要注意的问题
如果没有显式实现析构函数,那么编译器会自动生成一个什么都不做的析构函数。
如果构造函数中使用new、malloc分配的堆内存,就一定要显式实现析构函数,并在析构函数中释放堆内存,否则就会造成内存泄漏。
724

被折叠的 条评论
为什么被折叠?



