构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个成员变量都有一个合适的初始值,并在对象的生命周期只调用一次。
class Date { public: Date(int year = 1900, int month = 1, int day = 1) //带默认参数的构造函数 { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; };注:构造函数只是完成初始化的工作,不会负责给对象开辟空间
Date *p=new Date(2020,11,24) //new:完成给对象开辟空间 //构造函数:完成对象的初始化在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初值。 但是,不能将其称为类对象成员的初始化,构造函数中的语句只能称其为赋初值,因为**初始化只能有一次,**而构造函数可以多次赋初值。 以一个冒号开始,接着以一个逗号分隔的数据成员列表,每个成员变量后面根一个放在括号里面的初始值或表达式。
class Date { public: Date(int year, int month, int day) : _year(year) , _month(month) , _day(day) {} //Date(){} //无参构造 private: int _year; int _month; int _day; };注:
1.尽量使用初始化列表,自定义类型的成员变量一定会先使用初始化列表进行初始化 2.每个成员在初始化列表中只能出现一次(初始化只能进行一次) 3.成员变量的初始化与他们定义的顺序有关,和构造函数初始化列表中的先后顺序无关 3.类中包含以下成员,必须放在初始化列表位置进行初始化: 引用成员变量 、const成员变量 、类类型成员(该类没有默认构造函数) 4初始化列表用户可以不显示给出,但是不给出并不代表没有初始化列表,编译器会自动补全,只是补全时给成员变量中 放置的是随机值
只有单个形参,该形参是对本类类型对象的引用(一般用const修饰)在用已存在的类对象创建新对象时由编译器自动调用
Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; }在对象进行销毁时,由编译器自动调用,完成对象中资源的清理。(注:不负责回收空间)
typedef int DataType; class SeqList { public: SeqList(int capacity = 10) { _pData = (DataType*)malloc(capacity * sizeof(DataType)); assert(_pData); _size = 0; _capacity = capacity; } ~SeqList() { if (_pData) { free(_pData); // 释放堆上的空间 _pData = NULL; // 将指针置为空 _capacity = 0; _size = 0; } } private: int* _pData; size_t _size; size_t _capacity; };为了增强代码的可读性引入运算符重载。两个已经存在的对象之间的赋值运算。
Date& operator=(const Date& d) { if(this != &d) { _year = d._year; _month = d._month; _day = d._day; } return *this; }赋值运算符主要有四点:
1.参数类型 (类类型对象的引用) 2. 检测是否自己给自己赋值 3. 返回值,返回*this 4. 一个类如果没有显式定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝。
函数名字为:关键字operator后面接需要重载的运算符符号。 函数原型:返回值类型 operator操作符(参数列表)
// 左操作数是this指向的调用函数的对象 //bool operator=(Date* this, const Date& d2) bool operator=(const Date& d2) { return _year == d2._year && _month == d2._month && _day == d2._day; }不能重载的运算符只有5个:
. (成员访问运算符) .* (成员指针访问运算符) :: (域运算符) sizeof (长度运算符) ?: (条件运算符)注意:
不能引入新的自定义的运算符进行重载运算符重载时必须符合该运算符的含义如果该运算符重载为类的成员函数时,形参个数少一个(隐藏的this指针)为了区别后置++和前置++,给后置++多加了一个int型参数,在调用时int型的参数不用传递(同理–)将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。(除了被mutable修饰的成员变量) 注:mutable修饰类的成员变量,被mutable修饰的成员变量可以在const成员函数中修改
void Display() const//const修饰的成员函数 { cout << "Display () const" << endl; cout << "year:" << _year << endl; cout << "month:" << _month << endl; cout << "day:" << _day << endl << endl; }补充:
const对象可以调用其他const函数,传入的this指针是const T*this非const对象可以调用非const成员函数和const 成员函数 const成员函数只能调用其他const成员函数非const成员函数可以调用其他const成员函数和非const 成员函数这两个默认成员函数一般不用重新定义 ,编译器默认会生成。
Date* operator&() { return this; } const Date* operator&()const { return this; }代码如下:
class Date { public: //this指针:类类型* const,指向当前调用函数对象的指针 //谁调用指向谁,作为成员函数的第一个参数,只存在于成员函数中。 void Setdate(int year, int month, int day) { this->_year = year; _month = month; _day = day; } Date(int year = 1900, int month = 1, int day = 1)//构造函数 { _year = year; _month = month; _day = day; } Date(const Date& d)//拷贝构造函数 { _year = d._year; _month = d._month; _day = d._day; } void Display() const//const修饰的成员函数 { cout << "Display () const" << endl; cout << "year:" << _year << endl; cout << "month:" << _month << endl; cout << "day:" << _day << endl << endl; } ~Date()//析构函数 { cout << "~Date()" << endl; } bool operator==(const Date& d2)//运算符重载 { return _year == d2._year && _month == d2._month && _day == d2._day; } Date& operator=(const Date& d)//赋值运算符重载 { if(this != &d) { _year = d._year; _month = d._month; _day = d._day; } return *this; } //取地址及const取地址操作符重载 Date* operator&() { return this; } const Date* operator&()const { return this; } void diaplsy() { cout << "Display () const" << endl; cout << "year:" << _year << endl; cout << "month:" << _month << endl; cout << "day:" << _day << endl << endl; } private: int _year; int _month; int _day; };