文章目录
类的6个默认成员函数:
如果一个类中,一个成员也没有,这个类被简称为空类,空类中并不是什么都没有,任何一个类在我们什么都不写的情况下都会生成6个默认的成员函数
#include<iostream>
using namespace std;
class Date
{
public:
void setDate(int year=1900,int month=1,int day=1)
{
_year = year;
_month = month;
_day = day;
}
void PrintDate()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.setDate(2019, 6, 16);
d1.PrintDate();
Date d2;
d2.setDate();
d2.PrintDate();
system("pause");
return 0;
}
对于以上日期类,每次创建对象都需要使用setdate设置太过于麻烦
构造函数:
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次
构造函数的主要任务是初始化对象,不是构造对象
初始化在函数后面加:,然后进行初始化
特征:
1.函数名与类名一致
2.没有返回值
3.编译器自动调用
4.可以重载
代码示例:
#include<iostream>
using namespace std;
class Date
{
public:
//无参构造函数
Date()
{
}
//有参构造函数
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
void PrintDate()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.PrintDate();
Date d2(2019, 6, 16);
d2.PrintDate();
system("pause");
return 0;
}
d1调用无参构造函数的时候不用加括号,否则就变成函数声明了
有参构造函数如果写成全缺省函数就会报错,类中包含多个默认构造函数
如果用户没有显式定义一个构造函数,编译器会自动生成一个无参的构造函数
析构函数:
与构造函数功能相反,但是不是完成对象的销毁,局部对象销毁工作是由编译器完成的,而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作
特性:
1.析构函数名是类名加上~
2.既没有参数也没有返回值
3.一个类有且只有一个析构函数,如果没有显式定义,系统会自动生成默认的析构函数
4.对象声明周期结束时,C++编译系统会自动调用析构函数
代码示例:
typedef int Datatype;
class Seqlist
{
public:
Seqlist(int capacity)
{
_array = (Datatype*)malloc(sizeof(Datatype));
_size = 0;
_capacity = capacity;
}
~Seqlist()
{
if (_array)
{
free(_array);
_array = NULL;
_size = 0;
_capacity = 0;
}
}
private:
int* _array;
int _size;
int _capacity;
};
拷贝构造函数:
只有单个形参,该形参是对本类类型对象的引用,在用已存在的类类型对象创建新对象时由编译器自动调用
特征:
拷贝构造函数也是特殊的成员函数
1.拷贝构造函数是构造函数的一种重载形式
2.拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会导致无限递归
默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种被称为浅拷贝
单参数(const类类型&)--->如果没有按照&方式提供:编译器编译失败,导致无限递归
如果没有显式定义,系统生成默认的拷贝构造函数
代码示例:
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void PrintDate()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
Date(const Date& d)
{
_year=d._year ;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2(d1);
d1.PrintDate();
d2.PrintDate();
system("pause");
return 0;
}
默认拷贝构造函数:浅拷贝— 将一个对象中内容原封不动的拷贝到另一个对象中
Date--->编译器生成的默认拷贝构造
String---默认拷贝构造函数---一定会出错
当作成员函数的话,参数有当前默认的对象,所以只传一个参数就可以
赋值运算符重载:
运算符重载是具有特殊函数名的函数
函数名字为:关键字operator后面接需要重载的运算符符号
函数原型:返回值类型 operator操作符(参数列表)
以下运算符不可以重载:
.* :: sizeof ?: .
运算符的重载参数必须至少有一个类类型的操作数,不然可能造成无限递归
不可以改变内置整形本身的含义,+号不改变值,只返回结果,创建一个临时的变量
只能按照值的方式返回,不能返回引用
如果是自定义类型的,返回优先考虑引用,只需要考虑周期有没有函数的长
赋值运算符的参数类型是const类型的引用,因为不需要改变内容
实现步骤:
1.参数类型
2.返回值
3.检测是否自己给自己赋值
4.返回*this
函数后面加const,不允许修改成员变量的值
代码示例:
==的重载
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void PrintDate()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
Date(const Date& d)
{
_year=d._year ;
_month = d._month;
_day = d._day;
}
bool operator==(const Date& d)
{
if (_year == d._year&&
_month == d._month&&
_day == d._day)
{
return true;
}
return false;
}
bool operator!=(const Date& d)
{
if (!(_year == d._year&&
_month == d._month&&
_day == d._day))
{
return true;
}
return false;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2(d1);
d1.PrintDate();
d2.PrintDate();
Date d3(d1);
Date d4(2019, 6, 16);
d3.PrintDate();
d4.PrintDate();
if (d1 == d2)
{
cout << "d1与d2日期一致" << endl;
}
if (d3 != d4)
{
cout << "d3与d4日期不一致" << endl;
}
system("pause");
return 0;
}
=的重载
Date& operator=(const Date& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
+的重载
Date operator+(int days)
{
Date tmp(*this);
tmp._day += days;
return tmp;
}
这里的返回值不能是引用,因为tmp是栈上的,生命周期是函数的调用到结束
前置++的重载
Date& operator++()
{
_day + 1;
return *this;
}
对象的生命周期比函数长,可以返回引用
后置++的重载
Date operator++(int)
{
Date tmp(*this);
_day += 1;
return tmp;
}
参数类型给成int是为了和前置++形成重载
const成员函数:
将const修饰的类成员函数称为const成员函数,const实际修饰的是this指针,表明该成员函数不可以修改类中的任何成员变量
const相当于限制this指针,表明当前对象的内容不可以被修改
const Date* const
1. const对象可以调用非const成员函数吗?
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void TestFunc()
{
_day = 1;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
const Date d(2019, 6, 16);
d.TestFunc();
system("pause");
return 0;
}
非const成员函数可以对类里的成员变量进行修改,如果可以调用,那么限制就失去意义,代码不安全
2. 非const对象可以调用const成员函数吗?
void TestFunc()const
{
}
d的成员变量相当于可读写,TestFunc函数相当于只读函数,d此时可以被TestFunc读,可以调用,但是不可以通过TestFunc写
3. const成员函数内可以调用其它的非const成员函数吗?
const成员函数只可以读不可以写,而非const成员函数是可以写也可以读的,如果可以调用,代码不安全
4. 非const成员函数内可以调用其它的const成员函数吗?
不想贴图了,可读可写的函数调用一个只可以读的函数,没什么不安全的对吧?肯定是可以的
取地址及const取地址操作符重载:
一般函数代码示例:
Date* operator&()
{
return this;
}
const类型的&,如果可以调用&的重载,就可以修改成员变量的值,会矛盾
const类型的对象不能调用此类型的函数
const成员函数代码示例:
const Date* operator&()const
{
return this;
}