构造函数
每个类都分别定义了自己的对象被初始化的方式,类通过一个或几个特殊的成员函数来控制其对象的初始化过程,这样的函数叫做构造函数。构造函数(Constructor)是一种特殊的成员函数,它的名字和类名相同,没有返回值,不需要用户调用(用户也不能调用),而是在创建对象时自动执行。
作用:初始化对象的数据成员,无论何时只要类的对象被创建,就会执行构造函数。
类可以包含多个构造函数,不同构造函数之间必须在参数数量或参数类型上有所区别。
类通过一个特殊的构造函数来控制默认初始化过程,这个函数叫做默认构造函数。默认构造函数无需任何实参。
初始化类对象的规则:
1.如果存在类内的初始值,用它来初始化成员
2.否则,默认初始化该成员
某些类不能依赖于合成的默认构造函数,原因:
1.只有当类没有声明任何构造函数时,编译器才会自动地生成默认构造函数
2.对某些类来说,合成的默认构造函数可能执行错误的操作
3.有的时候编译器不能为某些类合成默认的构造函数
/*************************************************************************
> File Name: 构造函数.cpp
> Author: Tanswer_
> Mail: 98duxm@gmail.com
> Created Time: 2016年09月28日 星期三 22时15分30秒
************************************************************************/
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <stack>
#include <queue>
using namespace std;
class Student
{
private:
string name;
int age;
float score;
public:
//声明构造函数
Student(string ,int ,float);
void say();
};
//定义构造函数
Student::Student(string name1,int age1,float score1)
{
//一一赋值
name = name1;
age = age1;
score = score1;
}
void Student::say()
{
cout << name << "的年龄为" << age << ",成绩是" << score;
cout << endl;
}
int main()
{
//根据构造函数创建对象
Student stu("Tanswer",19,99.0f);
stu.say();
return 0;
}
C++构造函数的参数初始化表
对成员变量的初始化,除了在构造函数的函数体中一一赋值,还可以采用参数初始化表。
//在构造函数中采用参数初始化列表
Student::Student(string name1,int age1,float score1):name(name1), age(age1), score(score1) {}
其函数体为空。在函数首部与函数体之间增添了一个冒并加上 name(name1), age(age1), score(score1) 语句,这个语句的意思相当于函数体内部的 name = name1; age = age1; score = score1; 语句。
当成员变量非常多的时候,通过参数初始化列表进行赋值的优势就显现出来了,简洁明了。
另一个作用是,为 const 成员变量初始化。当成员变量被const修饰时,再为其直接赋值是错误的,初始化const成员变量的唯一方法就是参数初始化表。
C++析构函数
创建对象时,系统自动调用构造函数进行初始化,同样地,销毁对象时,系统也会自动调用一个函数来进行清理工作(例如回收创建对象时消耗的各种资源),这个函数被称为析构函数。
析构函数(Destructor)也是一种特殊的成员函数,没有返回值,不需要用户调用,而是在销毁对象时自动执行。与构造函数不同的是,析构函数的名字是在类名前面加一个”~“符号,而且析构函数没有参数,不能被重载,一个类只能有一个析构函数。
析构函数在对象被销毁前执行;要知道析构函数什么时候被调用,就要先知道对象什么时候被销毁。
析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作,使这部分内存可以分配给新对象使用。
一些执行析构函数的情况
1) 如果在一个函数中定义了一个对象(auto 局部变量),当这个函数运行结束时,对象就会被销毁,在对象被销毁前自动执行析构函数。
2) static 局部对象在函数调用结束时并不销毁,因此也不调用析构函数,只有在程序结束时(如 main 函数结束或调用 exit 函数)才调用 static 局部对象的析构函数。
3) 如果定义了一个全局对象,也只有在程序结束时才会调用该全局对象的析构函数。
4) 如果用 new 运算符动态地建立了一个对象,当用 delete 运算符释放该对象时,先调用该对象的析构函数。
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <stack>
#include <queue>
using namespace std;
class Student
{
private:
string name;
int age;
float score;
public:
//声明构造函数
Student(string ,int ,float);
//定义析构函数
~Student();
//普通成员函数
void say();
};
/*
//定义构造函数
Student::Student(string name1,int age1,float score1)
{
//一一赋值
name = name1;
age = age1;
score = score1;
}
*/
//在构造函数中采用参数初始化列表
Student::Student(string name1,int age1,float score1):name(name1), age(age1), score(score1) {}
Student::~Student()
{
cout << name << "再见" << endl;
}
void Student::say()
{
cout << name << "的年龄为" << age << ",成绩是" << score;
cout << endl;
}
int main()
{
Student stu1("Tanswer",19,99.0f);
stu1.say();
Student stu2("小明",20,80.0);
stu2.say();
cout << "main 函数即将执行结束" << endl;
return 0;
}
输出结果:
Tanswer的年龄为19,成绩是99
小明的年龄为20,成绩是80
main 函数即将执行结束
小明再见
Tanswer再见