【C++】类和对象(中)一篇文章带你学会六大默认成员函数

小明 2025-04-27 22:45:18 4

目录

  • 一、类的6个默认成员函数
  • 二、 构造函数
    • 2.1 概念
    • 2.2 特征
    • 三、析构函数
      • 3.1 概念
      • 3.2 特性
      • 四、拷贝构造函数
        • 4.1 概念
        • 4.2 特征
        • 五、赋值运算符重载
          • 5.1 运算符重载
          • 5.2 赋值运算符重载
          • 5.3 前置++和后置++重载
          • 六、日期类的实现
          • 七、const成员
          • 八、取地址及const取地址操作符重载
          • ���尾

            一、类的6个默认成员函数

            如果一个类中什么成员都没有,简称为空类。

            空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。

            默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。


            二、 构造函数

            2.1 概念

            对于下面的date类:

            class date
            {
            public:
            	void init(int year, int month, int day)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	void Print()
            	{
            		cout 
            	date d1;
            	date d2;
            	d1.init(2023, 6, 6);
            	d2.init(2023, 8, 8);
            	d1.Print();
            	d2.Print();
            	return 0;
            }
            
            public:
            	// 无参构造函数
            	date()
            	{
            		_year = 1;
            		_month = 1;
            		_day = 1;
            	}
            	// 带参构造函数
            	date(int year, int month, int day)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	void Print()
            	{
            		cout 
            	date d1; // 自动调用无参构造函数
            	d1.Print();
            	/*date d1();  // 错误,若调用构造函数时没有参数时,则对象名后面不能加()
            	d1.Print();*/ // 因为无法区分是实例化对象还是函数的声明
            	date d2(2023,6,6); // 自动调用带参构造函数
            	d2.Print();
            	return 0;
            }
            
            public:
            	 无参构造函数
            	//date()
            	//{
            	//	_year = 1;
            	//	_month = 1;
            	//	_day = 1;
            	//}
            	// 带参构造函数
            	date(int year, int month, int day)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	void Print()
            	{
            		cout 
            	// 这里将无参构造函数注释掉,再写一个带参构造函数,则不会生成无参构造函数
            	// 那么这里实例化对象就会报错 —— C2512	“date” : 没有合适的默认构造函数可用
            	date d1; 
            	d1.Print();
            	return 0;
            }
            
            public:
            	Time()
            	{
            		cout 
            private:
            	// 基本类型(内置类型)
            	int _year;
            	int _month;
            	int _day;
            	// 自定义类型
            	Time _t;
            };
            int main()
            {
            	Date d;
            	return 0;
            }
            
            public:
            	Time()
            	{
            		cout 
            private:
            	// 基本类型(内置类型)
            	int _year = 1970;
            	int _month = 1;
            	int _day = 1;
            	// 自定义类型
            	Time _t;
            };
            int main()
            {
            	Date d;
            	return 0;
            }
            
            public:
            	// 无参构造函数
            	date()
            	{
            		_year = 1;
            		_month = 1;
            		_day = 1;
            	}
            	// 全缺省构造函数
            	date(int year = 1, int month = 1, int day = 1)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	void Print()
            	{
            		cout 
            	date d1;	// 错误,无参构造函数和全缺省构造函数同为默认构造函数
            	d1.Print(); // 这里调用会有二义性会报错,E0339	类 "date" 包含多个默认构造函数
            	date d2(2023, 6, 6); // 自动调用带参构造函数
            	d2.Print();
            	return 0;
            }
            
            public:
            	Stack(size_t capacity = 3)
            	{
            		_array = (DataType*)malloc(sizeof(DataType) * capacity);
            		if (NULL == _array)
            		{
            			perror("malloc申请空间失败!!!");
            			return;
            		}
            		_capacity = capacity;
            		_size = 0;
            	}
            	void Push(DataType data)
            	{
            		// CheckCapacity();
            		_array[_size] = data;
            		_size++;
            	}
            	// 其他方法...
            	~Stack()
            	{
            		if (_array)
            		{
            			free(_array);
            			_array = NULL;
            			_capacity = 0;
            			_size = 0;
            		}
            	}
            private:
            	DataType* _array;
            	int _capacity;
            	int _size;
            };
            void TestStack()
            {
            	Stack s;
            	s.Push(1);
            	s.Push(2);
            }
            
            public:
            	~Time()
            	{
            		cout 
            private:
            	// 基本类型(内置类型)
            	int _year = 1970;
            	int _month = 1;
            	int _day = 1;
            	// 自定义类型
            	Time _t;
            };
            int main()
            {
            	Date d;
            	return 0;
            }
            // 程序运行结束后输出:~Time()
            // 在main方法中根本没有直接创建Time类的对象,为什么最后会调用Time类的析构函数?
            // 因为:main方法中创建了Date对象d,而d中包含4个成员变量,其中_year, _month,_day三个是内置类型成员,
            // 销毁时不需要资源清理,最后系统直接将其内存回收即可;
            // 而_t是Time类对象,所以在d销毁时,要将其内部包含的Time类的_t对象销毁,所以要调用Time类的析构函数。
            // 但是:main函数中不能直接调用Time类的析构函数,实际要释放的是Date类对象,
            // 所以编译器会调用Date类的析构函数,而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,
            // 目的是在其内部调用Time类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁
            // main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析构函数
            // 注意:创建哪个类的对象则调用该类的析构函数,销毁那个类的对象则调用该类的析构函数
            
            public:
            	Date(int year = 1970, int month = 1, int day = 1)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	// Date(const Date d)   // 错误写法,会引起层层递归
            	Date(const Date& d)		// 正确写法
            	{
            		_year = d._year;
            		_month = d._month;
            		_day = d._day;
            	}
            	void Print()
            	{
            		cout 
            	Date d1(2023, 8, 8);
            	Date d2(d1);
            	d1.Print();
            	d2.Print();
            	return 0;
            }
            
            public:
            	// 构造函数
            	Time()
            	{
            		_hour = 1;
            		_minute = 1;
            		_second = 1;
            	}
            	// 拷贝构造函数
            	Time(const Time& t)
            	{
            		_hour = t._hour;
            		_minute = t._minute;
            		_second = t._second;
            		cout 
            private:
            	// Date中没有显示定义构造函数,所以Date会生成默认的构造函数
            	// 内置类型不处理,自定义类型对象调用他自己的默认构造函数
            	
            	// 基本类型(内置类型)
            	int _year = 1970;
            	int _month = 1;
            	int _day = 1;
            	// 自定义类型
            	Time _t;
            };
            int main()
            {
            	Date d1;
            	// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
            	// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数
            	Date d2(d1);
            	return 0;
            }
            
            public:
            	Stack(size_t capacity = 10)
            	{
            		_array = (DataType*)malloc(sizeof(DataType) * capacity);
            		if (NULL == _array)
            		{
            			perror("malloc申请空间失败!!!");
            			return;
            		}
            		_capacity = capacity;
            		_size = 0;
            	}
            	Stack(const Stack& s)
            	{
            		_array = (DataType*)malloc(sizeof(DataType) * s._capacity);
            		if (NULL == _array)
            		{
            			perror("malloc申请空间失败!!!");
            			return;
            		}
            		memmove(s._array, _array, sizeof(DataType) * s._size);
            		_capacity = s._capacity;
            		_size = s._size;
            	}
            	void Push(DataType data)
            	{
            		// CheckCapacity();
            		_array[_size] = data;
            		_size++;
            	}
            	// 其他方法...
            	~Stack()
            	{
            		if (_array)
            		{
            			free(_array);
            			_array = NULL;
            			_capacity = 0;
            			_size = 0;
            		}
            	}
            private:
            	DataType* _array;
            	int _capacity;
            	int _size;
            };
            int main()
            {
            	Stack s1;
            	s1.Push(1);
            	s1.Push(2);
            	s1.Push(3);
            	s1.Push(4);
            	Stack s2(s1);
            	return 0;
            }
            
            public:
            	Date(int year, int month, int day)
            	{
            		cout 
            		cout 
            		cout 
            	Date temp(d);
            	return temp;
            }
            int main()
            {
            	Date d1(2023, 8, 8);
            	Test(d1);
            	return 0;
            }
            
            public:
            	Date(int year = 1970 , int month = 1, int day = 1)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	Date& operator=(const Date& d)
            	{
            		if (*this != d)
            		{
            			_year = d._year;
            			_month = d._month;
            			_day = d._day;
            		}
            		return *this;
            	}
            private:
            	int _year;
            	int _month;
            	int _day;
            };
            int main()
            {
            	Date d1(2023, 8, 8);
            	Date d2;
            	d2 = d1;
            	
            	return 0;
            }
            
            public:
            	Date(int year = 1900, int month = 1, int day = 1)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	int _year;
            	int _month;
            	int _day;
            };
            // 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
            Date& operator=(Date& left, const Date& right)
            {
            	if (&left != &right)
            	{
            		left._year = right._year;
            		left._month = right._month;
            		left._day = right._day;
            	}
            	return left;
            }
            // 编译失败:
            // error C2801: “operator =”必须是成员函数
            
            public:
            	Time()
            	{
            		_hour = 1; 
            		_minute = 1;
            		_second = 1;
            	}
            	Time& operator=(const Time& t)
            	{
            		if (this != &t)
            		{
            			_hour = t._hour;
            			_minute = t._minute;
            			_second = t._second;
            		}
            		return *this;
            	}
            private:
            	int _hour;
            	int _minute;
            	int _second;
            };
            class Date
            {
            private:
            	// 基本类型(内置类型)
            	int _year = 1970;
            	int _month = 1;
            	int _day = 1;
            	// 自定义类型
            	Time _t;
            };
            int main()
            {
            	Date d1;
            	Date d2;
            	d1 = d2;
            	return 0;
            }
            
            public:
            	Stack(size_t capacity = 10)
            	{
            		_array = (DataType*)malloc(capacity * sizeof(DataType));
            		if (nullptr == _array)
            		{
            			perror("malloc申请空间失败");
            			return;
            		}
            		_size = 0;
            		_capacity = capacity;
            	}
            	void Push(const DataType& data)
            	{
            		// CheckCapacity();
            		_array[_size] = data;
            		_size++;
            	}
            	~Stack()
            	{
            		if (_array)
            		{
            			free(_array);
            			_array = nullptr;
            			_capacity = 0;
            			_size = 0;
            		}
            	}
            private:
            	DataType* _array;
            	size_t _size;
            	size_t _capacity;
            };
            int main()
            {
            	Stack s1;
            	s1.Push(1);
            	s1.Push(2);
            	s1.Push(3);
            	s1.Push(4);
            	Stack s2;
            	s2 = s1;
            	return 0;
            }
            
            public:
            	Date(int year = 1900, int month = 1, int day = 1)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	// 前置++:返回+1之后的结果
            	// 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
            	Date& operator++()
            	{
            		_day += 1;
            		return *this;
            	}
            	// 后置++:返回+1之前的结果
            	// 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载
            	// C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递
            	// 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给this + 1
            	// 而temp是临时对象,因此只能以值的方式返回,不能返回引用
            	Date operator++(int)
            	{
            		Date temp(*this);
            		_day += 1;
            		return temp;
            	}
            private:
            	int _year;
            	int _month;
            	int _day;
            };
            
            public:
            	// 获取某年某月的天数
            	int GetMonthDay(int year, int month);
            	// 全缺省的构造函数
            	Date(int year = 1900, int month = 1, int day = 1);
            	// 拷贝构造函数
            	// d2(d1)
            	Date(const Date& d);
            	// 赋值运算符重载
            	// d2 = d3 - d2.operator=(&d2, d3)
            	Date& operator=(const Date& d);
            	// 析构函数
            	~Date();
            	// 日期+=天数
            	Date& operator+=(int day);
            	// 日期+天数
            	Date operator+(int day)const;
            	// 日期-天数
            	Date operator-(int day)const;
            	// 日期-=天数
            	Date& operator-=(int day);
            	// 前置++
            	Date& operator++();
            	// 后置++
            	Date operator++(int);
            	// 后置--
            	Date operator--(int);
            	// 前置--
            	Date& operator--();
            	// 运算符重载
            	bool operator(const Date& d)const;
            	// ==运算符重载
            	bool operator==(const Date& d)const;
            	// =运算符重载
            	bool operator = (const Date& d)const;
            	// 
            	static int MonthDay[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
            	if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
            	{
            		return 29;
            	}
            	return MonthDay[month];
            }
            // 全缺省的构造函数
            Date::Date(int year, int month, int day)
            {
            	_year = year;
            	_month = month;
            	_day = day;
            }
            // 拷贝构造函数
            // d2(d1)
            Date::Date(const Date& d)
            {
            	_year = d._year;
            	_month = d._month;
            	_day = d._day;
            }
            // 赋值运算符重载
            // d2 = d3 - d2.operator=(&d2, d3)
            Date& Date::operator=(const Date& d)
            {
            	if (*this != d)
            	{
            		_year = d._year;
            		_month = d._month;
            		_day = d._day;
            	}
            	return *this;
            }
            // 析构函数
            Date::~Date()
            {
            	//cout 
            	_day += day;
            	while (_day  GetMonthDay(_year, _month))
            	{
            		_day -= GetMonthDay(_year, _month);
            		_month++;
            		if (_month == 13)
            		{
            			_year++;
            			_month = 1;
            		}
            	}
            	return *this;
            }
            // 日期+天数
            Date Date::operator+(int day)const
            {
            	Date tmp(*this);
            	tmp += day;
            	return *this;
            }
            // 日期-=天数
            Date& Date::operator-=(int day)
            {
            	_day -= day;
            	while (_day 
            		// 这里_month需要先--,因为当前这个月的日期已经减完了
            		_month--;
            		if (_month == 0)
            		{
            			--_year;
            			_month = 12;
            		}
            		_day += GetMonthDay(_year, _month);
            	}
            	return *this;
            }
            // 日期-天数
            Date Date::operator-(int day)const
            {
            	Date tmp(*this);
            	tmp -= day;
            	return tmp;
            }
            // 前置++
            Date& Date::operator++()
            {
            	*this += 1;
            	return *this;
            }
            // 后置++
            Date Date::operator++(int)
            {
            	Date tmp(*this);
            	*this+=1;
            	return tmp;
            }
            // 后置--
            Date Date::operator--(int)
            {
            	Date tmp(*this);
            	*this -= 1;
            	return tmp;
            }
            // 前置--
            Date& Date::operator--()
            {
            	*this -= 1;
            	return *this;
            }
            // 运算符重载
            bool Date::operator(const Date& d)const
            {
            	if (_year  d._year)
            	{
            		return true;
            	}
            	else if (_year == d._year && _month  d._month)
            	{
            		return true;
            	}
            	else if (_year == d._year && _month == d._month && _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;
            }
            // 
            	return !(*this = d);
            }
            // 
            	return !(*this  d);
            }
            // !=运算符重载
            bool Date::operator != (const Date& d)const
            {
            	return !(*this == d);
            }
            // 日期-日期 返回天数
            int Date::operator-(const Date& d)const
            {
            	Date max = *this;
            	Date min = d;
            	int flag = 1;
            	if (max 
The End
微信