类的默认成员函数
类的默认成员函数
1、负责初始化和清理工作的,构造函数负责初始化,析构函数负责清理
2、拷贝复制,拷贝构造函数是使用同类对象初始化创建对象,赋值运算符重载主要是把一个对象赋值给另一个对象。
3、取地址运算符重载,包含取地址运算符重载和const取地址运算符重载。
1、构造函数
1.1、构造函数概念
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次。
1.2、构造函数特性
1、函数名与类名相同
2、无返回值
3、对象实例化编译器自动调用对应的构造函数
4、构造函数可以重载
5、如果类中没有显示定义构造函数,则C++编译器会自动生成一个构造函数,一旦用户显示定义,编译器将不再生成
6、无参构造函数和全缺省参数的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
#include <iostream>
using namespace std;
class Date1
{
public:
void Display()
{
cout << _year << " " << _month << " " << _day << endl;
}
void SetDate(int yeay, int month, int day)
{
_year = yeay;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
class Date2
{
public:
//无参构造
Date2 ()
{
}
//带参构造
Date2 (int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
void TestDate2()
{
Date2 d3;//调用无参构造
Date2 d4(2020, 3, 27);//调用带参构造
//注意:调用无参构造不能带括号,不然会当成函数声明
Date2 d5();//会被当做函数d5无参,返回Date类的函数声明。
}
class Date3
{
public:
无参构造
//Date3 ()
//{
//}
带参构造
//Date3 (int year, int month, int day)
//{
// _year = year;
// _month = month;
// _day = day;
//}
private:
int _year;
int _month;
int _day;
};
void TestDate3()
{
Date3 d6;//此处调用的是类的默认构造函数,故可以成功创建对象。
}
class Date4
{
public:
//无参构造
Date4 ()
{
_year = 2020;
_month = 3;
_day = 27;
}
//全缺省参数构造
Date4 (int year = 2020, int month = 3, int day = 27)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
void TestDate4()
{
//Date4 d;//报错,因为Date4中含有多个构造函数,创建对象时不知该调用哪个。
}
class Time
{
public:
Time()
{
cout << "Time ()" << endl;
}
Time()
{
_hour = 0;
_minute = 0;
_second = 0;
}
private:
int _hour;
int _minute;
int _second;
};
class Date5
{
private:
//内置类型
int _year;
int _month;
int _day;
//自定义类型
Time _t;
};
void TestDate5()
{
Date5 d5;
}
//成员变量的命名风格
class Date6
{
public:
Date6(int year)
{
_year = year;
}
private:
int _year;
};
//成员变量的另外一种命名风格
class Date7
{
public:
Date7 (int year)
{
m_year = year;
}
private:
int m_year;
};
int main()
{
Date1 d1, d2;
d1.SetDate(2020, 1, 24);
d2.SetDate(2020, 3, 26);
d1.Display();
d2.Display();
system("pause");
return 0;
}
2、析构函数
2.1、析构函数概念
析构函数是对象在销毁时候回自动调用析构函数,完成一些资源的释放工作。
2.2、析构函数特征
1、析构函数名是在类名称前面加上~
2、无参数无返回值
3、一个类有且只有一个析构函数,若未现实定义,有编译器给出默认析构函数
4、对象生命周期结束时,C++编译器自动调用析构函数。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cassert>
#include <cstring>
using namespace std;
typedef int DataType;
class SeqList
{
public:
SeqList(int capacity = 10)
{
_SeqList = (DataType*)malloc(capacity * sizeof(DataType));
assert(_SeqList);
_size = 0;
_capacity = capacity;
}
~SeqList()
{
if (_SeqList)
{
free(_SeqList);
_SeqList = NULL;
_capacity = 0;
_size = 0;
}
}
private:
DataType* _SeqList;
size_t _size;
size_t _capacity;
};
class String
{
public:
String(const char* str = "zhangsan")
{
_str = (char*)malloc(strlen(str) + 1);
strcpy(_str, str);
}
~String()
{
cout << "~String()" << endl;
free(_str);
_str = NULL;
}
private:
char* _str;
};
class Person
{
private:
String _name;
int _age;
};
int main()
{
String _name;
Person per;
system("pause");
return 0;
}
3、拷贝构造函数
3.1、拷贝构造函数的概念
只有一个形参,该形参是对本类类型对象的引用(一般常用const修饰),在已存在的类类型对象创建新对象时由编译器自动调用。
3.2、拷贝构造函数的特征
1、拷贝构造函数是构造函数的一个重载形式
2、拷贝构造函数的参数只有一个且必须使用引用传参(防止无限递归)。
3、若未显示定义,则系统默认生成的拷贝构造函数为浅拷贝。(对象按内存存储的字节序完成拷贝)。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
class Date1
{
public:
Date1(int year = 2020, int month = 3, int day = 27)
{
_year = year;
_month = month;
_day = day;
}
//此处必须注意要穿引用,若是传值的话会出现无限递归调用
Date1(const Date1& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
class Date2
{
public:
Date2(int year = 2020, int month = 3, int day = 27)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
class String
{
public:
String(const char* str = "zhangsan")
{
_str = (char*)malloc(strlen(str) + 1);
strcpy(_str, str);
}
~String()
{
cout << "~String()" << endl;
//free(_str);
//_str = NULL;
}
private:
char* _str;
};
int main()
{
Date1 d1;
Date1 d2(d1);
Date2 d3;
Date2 d4(d3);
String s1("Hello,World!");
String s2(s1);
system("pause");
return 0;
}
4、运算符重载
4.1、运算符重载的概念
C++为了增强代码的可读性,引入了运算符重载,运算符重载是具有特殊函数名的函数。
函数名称为:关键字operator后面接所需要重载的运算符符号
函数原型:返回值类型operator操作符(参数列表)
4.2、运算符重载的特征
注:
1、不能通过连接其他符号来创建新的操作符:比如operator@
2、重载操作符必须有一个类类型或者枚举类型的操作数
3、用于内置类型的操作符,其含义不能改变,例如:内置类型+,不能改变其含义
4、作为类成员的重载函数时,其形参看起来比操作数的数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
5、. * :: sizeof ? : 不能重载
5、赋值运算符重载
5.1、赋值运算符重载概念
赋值运算符重载
1、参数类型
2、返回值
3、检测是否自己给自己赋值
4、返回*this
5、若是没有显示定义,编译器会自动生成,完成对象按字节序的值拷贝
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
class Date1
{
public:
Date1(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
public:
int _year;
int _month;
int _day;
};
//若是operator做全局的,那么封装性不能被保证
//此处可以做出友元或者直接做成成员函数
bool operator==(const Date1& d1, const Date1& d2)
{
return d1._year == d2._year && d1._month == d2._month && d1._day == d2._day;
}
class Date2
{
public:
Date2(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
//bool operator==(Date* this, const Date& d2)
//此处左操作数是this指向的调用函数的对象
bool operator==(const Date2& d2)
{
return _year == d2._year && _month == _month && _day == _day;
}
public:
int _year;
int _month;
int _day;
};
class Date3
{
public:
Date3(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
Date3(const Date3& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
Date3& operator=(const Date3& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
}
public:
int _year;
int _month;
int _day;
};
class Date4
{
public:
Date4(int year = 2020, int month = 3, int day = 28)
{
_year = year;
_month = month;
_day = day;
}
bool operator==(const Date4& d2)
{
return _year == d2._year && _month == _month && _day == _day;
}
public:
int _year;
int _month;
int _day;
};
class String
{
public:
String(const char* str = "")
{
_str = (char*)malloc(strlen(str) + 1);
strcpy(_str, str);
}
~String()
{
cout << "~String()" << endl;
free(_str);
}
private:
char* _str;
};
int main()
{
Date1 d1(2020, 3, 27);
Date1 d2(2020, 3, 28);
cout << (d1 == d2) << endl;
Date2 d3(2020, 3, 28);
Date2 d4(2020, 3, 28);
cout << (d3 == d4) << endl;
Date4 d5;
Date4 d6(2020, 3, 28);
d5 = d6;
cout << (d5 == d6) << endl;
String s1("Hello");
String s2("World");
s1 = s2;
system("pause");
return 0;
}
6、const成员
6.1、const修饰的成员函数
将const修饰的类成员函数称为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明该成员函数中不能对类的任何成员进行修改
注:
1、非const对象可以调用const成员函数
2、非const成员函数可以调用其他const成员函数
#include <iostream>
using namespace std;
//const修饰的成员函数实际上修饰的是成员函数的this指针
//表面该成员函数中不能对类的任何成员进行修改
//非const对象可以调用const成员函数
//非const成员函数可以调用const成员函数
class Date
{
public:
Date(int year = 2020, int month = 3, int day = 28)
{
_year = year;
_month = month;
_day = day;
}
void Display()
{
cout << "Display()" << endl;
cout << "year:" << _year << endl;
cout << "month:" << _month << endl;
cout << "day:" << _day << endl;
}
void Display()const
{
cout << "Display()const" << endl;
cout << "year:" << _year << endl;
cout << "month:" << _month << endl;
cout << "day:" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.Display();
const Date d2;
d2.Display();
system("pause");
return 0;
}
7、取地址运算符重载和const取地址运算符重载
#include <iostream>
using namespace std;
//取地址运算符重载
//const取地址运算符重载
//注:这两个运算符重载一般默认给出, 若无特殊情况,则无需重载。
class Date
{
public:
Date* operator&()
{
return this;
}
const Date* operator&()const{
return this;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
system("pause");
return 0;
}