目录
1. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数
一、缺省参数
(一)缺省参数概念
- 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参
#include<iostream>
using namespace std;
void test(int a=1)
{
cout << a << endl;
}
int main()
{
test(11);//11
test();//1
return 0;
}
(二)缺省参数分类
1. 全缺省参数
#include<iostream>
using namespace std;
void test(int a = 1, int b = 2, int c = 3, int d = 4)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
cout << "d = " << d << endl;
cout << endl;
}
int main()
{
test();//a,b,c,d都使用缺省的
return 0;
}
2. 半缺省参数(缺省部分参数)
#include<iostream>
using namespace std;
void test(int a,int b=2,int c=3,int d=4)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
cout << "d = " << d << endl;
cout << endl;
}
int main()
{
test();//a,b,c,d都使用缺省的
test(11);//给a传参,b、c、d使用缺省的
test(11,22);//给a、b传参,c和d使用缺省的
test(11, 22, 33);
return 0;
}
3. 注意
- 半缺省参数必须从右往左依次来给出,不能间隔着给(也就是调用时,传参从左向右依次传参,不能空缺)
- 缺省参数不能在函数声明和定义中同时出
二、函数重载
(一)基本概念
- 是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题
(二)举例
#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
// 2、参数个数不同
void test()
{
cout << "test()" << endl;
}
void test(int a)
{
cout << "test(int a)" << endl;
}
// 3、参数类型顺序不同
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
int main()
{
Add(1, 2);
Add(1.4, 5.7);
test();
test(66);
f(11, 'a');
f('a', 16);
return 0;
}
三、构造函数基本概念
- 构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次
四、构造函数特性
- 构造函数的主要任务并不是开空间创建对象,而是初始化对象
(一)特征
1. 函数名与类名相同
2. 无返回值(void也不行)
3. 对象实例化时编译器自动调用对应的构造函数
4. 构造函数可以重载
(二)举例:不利用构造函数初始化对象
#include<iostream>
using namespace std;
class Date
{
private:
int _year;
int _month;
int _day;
public:
void Init(int year, int month, int day)//定义初始化函数
{
_year = year;
_month = month;
_day = day;
}
void Print()//打印函数
{
cout << _year << "-" << _month << "-" << _day << endl;
}
};
int main()
{
Date d1;
d1.Init(2022, 8, 9);
d1.Print();//2022-8-9
return 0;
}
(三)举例:利用构造函数初始化对象
#include<iostream>
using namespace std;
class Date
{
private:
int _year;
int _month;
int _day;
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()//打印函数
{
cout << _year << "-" << _month << "-" << _day << endl;
}
};
int main()
{
Date d1(2022, 8, 9);//对象实例化时,自动调用构造函数
d1.Print();//2022-8-9
return 0;
}
(四)举例
1. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数
//举例1:类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数
#include<iostream>
using namespace std;
class Date
{
private:
int _year;
int _month;
int _day;
public:
void Print()//打印函数
{
cout << _year << "-" << _month << "-" << _day << endl;
}
};
int main()
{
Date d1;//d1调用系统生成的无参构造函数
d1.Print();
return 0;
}
2. 一旦用户显式定义编译器将不再生成
3. 解决调用默认构造函数的方法
- 第一种调用系统默认的无参构造函数
- 第二种自己实现无参构造函数
#include<iostream>
using namespace std;
class Date
{
private:
int _year;
int _month;
int _day;
public:
Date()
{
_year=0;
_month = 1;
_day = 2;
}
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()//打印函数
{
cout << _year << "-" << _month << "-" << _day << endl;
}
};
int main()
{
Date d1;
d1.Print();
Date d2(2022, 9, 14);
d2.Print();
return 0;
}
- 第三种利用全缺省的构造函数
#include<iostream>
using namespace std;
class Date
{
private:
int _year;
int _month;
int _day;
public:
Date(int year=2021, int month=1, int day=8)
{
_year = year;
_month = month;
_day = day;
}
void Print()//打印函数
{
cout << _year << "-" << _month << "-" << _day << endl;
}
};
int main()
{
Date d1;
d1.Print();
Date d2(2022, 9, 14);
d2.Print();
return 0;
}
(五)单参数构造函数隐式类型转换
#include<iostream>
using std::cout;
using std::endl;
class A
{
public:
A(int a = 77) :_a(a)
{
cout << "A()" << endl;
}
A(const A& o)
{
cout << "A(const A& ) " << endl;
}
~A()
{
cout << "~A()" << endl;
}
void Print()const
{
cout << _a << endl;
}
private:
int _a;
};
int main()
{
//有名对象
A a1(1);
A a2 = 3;
const A& a3 = 4;
cout << "a1:";
a1.Print();
cout << "a2:";
a2.Print();
cout << "a3:";
a3.Print();
}
五、注意
- 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数
六、运算符重载
返回值类型 operator操作符(参数列表)
日期类的实现
//Date.h
#pragma once
#include<iostream>
using std::cout;
using std::cin;
using std::endl;
using std::ostream;
using std::istream;
class Date
{
public:
friend void operator<<(ostream& out,const Date& d);//重载<<(out是cout的别名)
friend void operator>>(istream& in, Date& d);//重载>>
Date(int y = 1, int m = 2, int d = 3);
Date(const Date& d);
bool operator<(const Date& d)const;
bool operator==(const Date& d)const;
bool operator<=(const Date& d)const;
bool operator>(const Date& d)const;
int GetDay(int y, int m) const;//获取某一年某月的天数
Date& operator+=(int d);
Date operator+(int d)const;
Date& operator-=(int d);
Date operator-(int d)const;
Date& operator++();//前置++
Date operator++(int);//后置++(使用int参数进行占位)
void Print()const;
private:
int _year;
int _month;
int _day;
};
//Date.cpp
#include"Date.h"
Date::Date(int y, int m, int d)
{
_year = y;
_month = m;
_day = d;
}
Date::Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
bool Date::operator<(const Date& d) const
{
if (_year < d._year)
return true;
if (_year == d._year and _month < d._month)
return true;
if (_year == d._year and _month < d._month and _day < d._day)
return true;
else
return false;
}
bool Date::operator==(const Date& d) const
{
return _year == d._year && _month == d._month && _day == d._day;
}
bool Date::operator<=(const Date& d) const
{
return *this < d || *this == d;//此处相当于直接调用上面定义过的
}
bool Date::operator>(const Date& d) const
{
return !(*this <= d);
}
int Date::GetDay(int y, int m) const
{
static int a[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (m == 2)//某年是闰年的时候,2月为29
{
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
{
return 29;
}
}
return a[m];
}
Date& Date::operator+=(int d)
{
_day += d;
while (_day > GetDay(_year, _month))
{
_day -= GetDay(_year, _month);
++_month;
if (_month == 13)
{
++_year;
_month = 1;
}
}
return *this;
}
Date Date::operator+(int d) const
{
Date tmp;
tmp = *this;
tmp._day += d;
while (tmp._day > GetDay(tmp._year, tmp._month))
{
tmp._day -= GetDay(tmp._year, tmp._month);
++tmp._month;
if (tmp._month == 13)
{
tmp._year++;
tmp._month = 1;
}
}
return tmp;
}
Date& Date::operator-=(int d)
{
_day = _day - d;
while (_day <= 0)
{
--_month;
if (_month == 0)
{
--_year;
_month = 12;
}
_day = _day + GetDay(_year, _month);
}
return *this;
}
Date Date::operator-(int d) const
{
Date tmp(*this);
tmp._day = tmp._day - d;
while (tmp._day <= 0)
{
--tmp._month;
if (tmp._month == 0)
{
--tmp._year;
tmp._month = 12;
}
tmp._day += GetDay(tmp._year, tmp._month);
}
return tmp;
}
Date& Date::operator++()//前置++
{
*this += 1;
return *this;
}
Date Date::operator++(int)//后置++
{
Date tmp(*this);
*this += 1;
return tmp;
}
void Date::Print() const
{
cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
void operator<<(ostream& out, const Date& d)
{
out << d._year << "年" << d._month << "月" << d._day << "日";
}
void operator>>(istream& in, Date& d)//重载>>
{
in >> d._year >> d._month >> d._day;
}
//test.cpp
#include"Date.h"
int main()
{
Date d1(2021, 11, 25);
d1 += 1000;
cout << "d1:";
d1.Print();//2024年8月21日
cout << endl;
cout << "d2:";
Date d2 = d1 + 60;
d2.Print();//2024年10月20日
cout << endl;
cout << "d2:";
d2 -= 1068;
d2.Print();//2021年11月17日
cout << endl;
cout << "d3:";
Date d3 = d2 - 800;
d3.Print();//2019年9月9日
cout << endl;
cout << "d4:";
Date d4 = d1;
++d4;
d4.Print();
cout << endl;
cout << "d5:";
Date d5 = d1;
d5++;
d5.Print();
cout << endl;
cout << "<<重载:" << endl;
cout << d1;
cout << endl;
cout << ">>重载:" << endl;
Date d6;
cin >> d6;
cout << d6;
return 0;
}