文章目录
前言
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
类的数据成员多为私有的,要对它们进初始化,必须用一个公有函数来进行。同时这个函数应该在且仅在定义对象时自动执行一次。这个函数就是构造函数。它由系统自动调动,用户不可以调动。
当一个对象被定义时,C++自动调用构造函数对该对象进行初始化,那么当一个对象的生命周期结束时,C++也会自动调用一个函数进行扫尾工作,这个特殊的成员函数就是析构函数。
一、构造函数的作用和用法
作用:初始化
特点:
(1)函数名用类名,没有返回值
(2)访问权限必为public
(3)系统自动调用在定义对象时
(4)系统默认分配构造函数,没有函数体,默认参数,不能和函数重载一起用,否则冲突!
下面是一个时间的类的代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Time
{
public:
//无参构造函数
Time()
{
hour = 0;
minute = 0;
second = 0;
}
//有参构造函数
Time(int h,int m,int s)
{
hour = h;
minute = m;
second = s;
}
//用于设置时间的函数
void setTime(int h, int m, int s)
{
hour = h;
minute = m;
second = s;
}
//用于显示时间的函数
void showTime()
{
cout << hour << " " << minute << " " << second << endl;
}
private:
int hour;
int minute;
int second;
};
int main()
{
Time t1, t2(1, 2, 3);
t1.showTime();
t2.showTime();
return 0;
}
运行结果如下:
此构造函数重载了两次。
以下为默认函数,相当于无参构造函数与有参构造函数相结合,且两者只能二选一。
Time(int h=10, int m=10, int s=10)
{
hour = h;
minute = m;
second = s;
}
以下是参数初始化列表相当于有参构造函数,与其二选一使用。
二、析构函数
作用:对象撤销前的清理工作
特点:
(1)函数名用~加类名(){}
(2)没有返回值类型,没有参数
(3)调用:在对象撤销时类外系统自动调用
析构函数代码如下:
~Time()
{
cout << "deconstructor called" << endl;
}
其中“ deconstructor called”仅用于显示析构是否成功。
将此析构函数加入到上面时间类的代码
析构的顺序为:
1.调用析构函数
2.撤销t2,t1
3.输出两遍
简单的总结与训练
顺序为先构造后虚构
下面我们来尝试一个简单的题目:
首先定义一个学生类要求数据包含学号,姓名,性别
函数包括构造函数(同时输出constructor called),显示函数,析构函数 (同时输出deconstructor called)
参考答案如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;
class Student
{
public:
Student(int m, string n, char s)
{
num = m;
name = n;
sex = s;
cout << "constructor called" << endl;
}
void display()
{
cout << "num:" << num << endl;
cout << "name:" << name << endl;
cout << "sex:" << sex << endl;
}
~Student()
{
cout << "deconstructor called" << endl;
}
private:
int num;
string name;
char sex;
};
int main()
{
Student stu1(1001, "Liming", 'm');
stu1.display();
Student stu2(1002, "Wangfang", 'f');
stu2.display();
return 0;
}
运行结果为:
由此推断执行顺序为:stu1构造->stu1.display->stu2构造->stu2.display->stu2析构->stu1析构
三、拷贝构造函数
上面的时间的类代码中假设我们想将t2的数据赋给t1,我们用Time t1(t2);将t2赋给t1可行吗?
答案必然是否定的,因为“=”是库函数的一种运算函数,只能对系统的内置类型进行运算,那么我们该怎么做呢?
这时我们就可以利用 拷贝构造函数
作用:用一个已经初始化过的对象给新的对象初始化
函数名:类名+新对象名+(已有对象)
此函数利用了this指针的概念,其实类的所有成员函数必有类作参数只是在写的时候省略了
例如上面Time中的函数
//用于显示时间的函数
void showTime()
{
cout << hour << " " << minute << " " << second << endl;
}
它的含义其实是:
void showTime(Time * this)
{
cout <<this->hour << " " << this->minute << " " << this->second << endl;
}
即类的成员函数的第一个参数都是当前类的对象的指针,即this指针。
当我们想写一个拷贝类的函数时,还是以Time为例,我们会写成
void copy(Time t1, Time t2)
{
t1.hour = t2.hour;
t1.minute = t2.minute;
t1.second = t2.second;
}
但这种写法忽略了隐藏的指向当前类的对象的指针
正确写法应该为:
Time(const Time &t)
{
hour = t.hour;
minute = t.minute;
second = t.second;
}
总结
以上就是今天要讲的内容,本文仅仅简单地介绍了构造,析构,拷贝构造函数的使用。
让我们做一个小练习复习一下今天的内容:
定义一个复数类Complex,数据成员包含实部real 虚部img,成员函数包括构造函数,输出函数,求两个函数的和add(const Complex &c)
参考答案如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Complex
{
public:
Complex(int r = 0, int i = 0)
{
real = r;
img = i;
}
void display()
{
cout << "相加结果为:" << real << "+" << img << "i" << endl;
}
Complex add(const Complex &c)
{
Complex s;
s.real = real + c.real;
s.img = img + c.img;
return s;
}
private:
int real;
int img;
};
int main()
{
Complex c1(2, 3);
Complex c2(4, 5);
Complex c3;
c3 = c1.add(c2);
c3.display();
return 0;
}
最后一个小tips:注意调用时第一个参数写在外面,括号里从第二个参数开始写
本篇文章就到这里了,祝大家成绩都能蒸蒸日上。