目录
前言
上一篇文章我们说了类的基本定义方式,类实例化对象,this指针,以及封装的好处,今天我们来谈谈类中的默认成员函数。默认成员函数就是没有显式实现,编译器会自动生成的成员函数称为默认成员函数。一个类,我 们不写的情况下编译器会默认生成以下6个默认成员函数,需要注意的是这6个中最重要的是前4个,最后两个取地址重载不重要,我们稍微了解⼀下即可。
一、构造函数
1、构造函数的作用
2、构造函数的特点
(1) 构造函数的函数名与类名相同
(2) 构造函数没有返回值,void也不需要写
(3) 构造函数可以重载
(4) 构造函数在对象实例化时自动调用
我们来看一个Date类的例子
class Date
{
public:
//构造函数
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
//构造函数
Date()
{
_year = 1;
_month = 1;
_day = 1;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2025, 1, 10);
d1.Print(); //2025-1-10
Date d2;
d2.Print(); //1-1-1
return 0;
}
这个日期类有两个构造函数,构成重载,而构造函数的调用也很奇特,就是在实例化对象的时候传参,d2没有传参,他会去调用到无参的构造函数,虽然没有参数,但一定不能写成Date d2(),编译会报错,因为编译器无法区分是对象实例化还是函数声明。
构造函数是默认成员函数,我们不写编译器会默认生成一个,我们就先来看看默认构造函数。
3、默认构造函数
先来了解一下默认构造函数的概念,如果类中没有显示定义构造函数,编译器会生成一个无参的默认构造函数,但是只要显示定义了,编译器就不再生成,而编译器生成的默认构造函数,无参构造函数,全缺省构造函数都叫默认构造函数,且默认构造函数只能有一个,无参构造函数和全缺省构造函数构成重载,但是调用时会存在歧义,调用不明确。
上面我们举的那个例子,下面的构造函数就是无参构造函数,也就是默认构造函数,但是因为我们显示定义了,所以编译器就不再生成了。
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2025, 1, 10);
d1.Print();
//d2编译报错,没有合适的默认构造可用
Date d2;
d2.Print();
return 0;
}
d2没有传参,想用默认构造,但是没有显示定义无参构造或者全缺省构造,又因为我们显示定义了构造函数,所以编译器也不会再生成,d2就没有默认构造可用,就会报错。
再来看一个栈的例子
typedef int STDataType;
class Stack
{
public:
Stack(int n = 4)
{
_a = (STDataType*)malloc(sizeof(STDataType) * n);
_capacity = n;
_top = 0;
}
private:
STDataType* _a;
size_t _capacity;
size_t _top;
};
int main()
{
Stack st;
return 0;
}
这里st也是用的全缺省的构造函数
如果我们一个构造函数也不显示定义,就用编译器生成的,那么编译器生成的无参的默认构造函数会干什么呢?
编译器生成的默认构造函数对与内置类型不做处理,对与自定义类型会去调用它的默认构造