【C++庖丁解牛】默认成员函数

2024-03-05 1852阅读

温馨提示:这篇文章已超过393天没有更新,请注意相关的内容是否还可用!


📙 作者简介 :RO-BERRY

📗 学习方向:致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识

📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持


【C++庖丁解牛】默认成员函数


目录

  • 前言
  • 1. 构造函数
    • 1.1 概念
    • 1.2 特性
    • 2.析构函数
      • 2.1 概念
      • 2.2 特性
      • 3. 拷贝构造函数
        • 3.1 概念
        • 3.2 特征
        • 4.赋值运算符重载
          • 4.1 运算符重载
          • 4.2 赋值运算符重载
          • 4.3 前置++和后置++重载
          • 5.const成员
          • 6.取地址及const取地址操作符重载

            前言

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

            空类中真的什么都没有吗?

            并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。

            这六个函数包括:构造函数、析构函数、拷贝构造函数、赋值运算符重载、普通对象取地址重载、const修饰对象的取地址重载。

            所有的默认成员函数都是可以由编译器自己生成的,编译器会自己生成一个默认的函数。同时我们也可以自己定义这些函数,那么编译器就会直接使用我们定义好的函数而不会自己再生成了。

            1. 构造函数

            1.1 概念

            对于以下Date类:

            #include
            using namespace std;
            class Date
            {
            public:
            	void Init(int year, int month, int day)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	void Print()
            	{
            		cout 
            	Date d1;
            	d1.Init(2022, 7, 5);
            	d1.Print();
            	Date d2;
            	d2.Init(2022, 7, 6);
            	d2.Print();
            	return 0;
            }
            
            public:
                    // 1.无参构造函数
                    //Date()
                    //{
                    //      _year = 1;
                    //      _month = 1;
                    //      _day = 1;
                    //}
                     2.带参构造函数
                    //Date(int year, int month, int day)
                    //{
                    //      _year = year;
                    //      _month = month;
                    //      _day = day;
                    //}
            //这两个函数构成重载,但是无参调用存在歧义,不能同时存在
                    //Date(int year, int month, int day)
                    //{
                    //      _year = year;
                    //      _month = month;
                    //      _day = day;
                    //}
                    //Date(int year=1, int month=1, int day=1) 全缺省
                    //{
                    //      _year = year;
                    //      _month = month;
                    //      _day = day;
                    //}
                    Date(int year=1, int month=1, int day=1) //全缺省
                    {
                           _year = year;
                           _month = month;
                           _day = day;
                    }
            //使用全缺省这里可以传一个两个三个或者不传,就比较方便
            private:
                    int _year;
                    int _month;
                    int _day;
            };
            void TestDate()
            {
                    Date d1; // 调用无参构造函数
                    //这里可不可以写Date d1()
                    //不可以 这里如果这样写就和函数声明分不开了
                    //比如Date f()    --函数名为f。返回值为Date
                    Date d2(2015, 1, 1); // 调用带参的构造函数
                    // 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
                    // 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
                    // warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)
                    Date d3();
            }
            
            public:
            	/*
            	// 如果用户显式定义了构造函数,编译器将不再生成
            	Date(int year, int month, int day)
            	{
            	_year = year;
            	_month = month;
            	_day = day;
            	}
            	*/
            	void Print()
            	{
            		cout 
            	    // 将Date类中构造函数屏蔽后,代码可以通过编译,因为编译器生成了一个无参的默认构造函数
            		// 将Date类中构造函数放开,代码编译失败,因为一旦显式定义任何构造函数,编译器将不再生成
            		// 无参构造函数,放开后报错:error C2512: “Date”: 没有合适的默认构造函数可用
            	Date d1;
            	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 = 1900;
            		_month = 1;
            		_day = 1;
            	}
            	Date(int year = 1900, int month = 1, int day = 1)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            private:
            	int _year;
            	int _month;
            	int _day;
            };
            // 以下测试函数能通过编译吗?
            void Test()
            {
            	Date d1;
            }
            
            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;
            };
            int main()
            {
            	Stack s;
            	s.Push(1);
            	s.Push(2);
            	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(int year = 1900, 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;
            	}
            private:
            	int _year;
            	int _month;
            	int _day;
            };
            int main()
            {
            	Date d1;
            	Date d2(d1);
            	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:
            	// 基本类型(内置类型)
            	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(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(s1);
            	return 0;
            }
            
            public:
            	Date(int year, int minute, int day)
            	{
            		cout 
            		cout 
            		cout 
            	Date temp(d);
            	return temp;
            }
            int main()
            {
            	Date d1(2022, 1, 13);
            	Test(d1);
            	return 0;
            }
            
            public:
            	Date(int year = 1900, int month = 1, int day = 1)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	//private:
            	int _year;
            	int _month;
            	int _day;
            };
            // 这里会发现运算符重载成全局的就需要成员变量是公有的,那么问题来了,封装性如何保证?
            // 这里其实可以用我们后面学习的友元解决,或者干脆重载成成员函数。
            bool operator==(const Date& d1, const Date& d2)
            {
            	return d1._year == d2._year
            		&& d1._month == d2._month
            		&& d1._day == d2._day;
            }
            void Test()
            {
            	Date d1(2018, 9, 26);
            	Date d2(2018, 9, 27);
            	cout 
            public:
            	Date(int year = 1900, int month = 1, int day = 1)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	// bool operator==(Date* this, const Date& d2)
            	// 这里需要注意的是,左操作数是this,指向调用函数的对象
            	bool operator==(const Date & d2)
            	{
            		return _year == d2._year;
            		&& _month == d2._month
            			&& _day == d2._day;
            	}
            private:
            	int _year;
            	int _month;
            	int _day;
            };
            
            public:
            	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;
            	}
            	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;
            };
            
            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;
            	}
            	// 后置++:
            	// 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载
            	// 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;
            };
            int main()
            {
            	Date d;
            	Date d1(2022, 1, 13);
            	d = d1++;    // d: 2022,1,13   d1:2022,1,14
            	d = ++d1;    // d: 2022,1,15   d1:2022,1,15
            	return 0;
            }
            
            public:
            	Date(int year, int month, int day)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	void Print()
            	{
            		cout 
            		cout 
            	Date d1(2022, 1, 13);
            	d1.Print();
            	const Date d2(2022, 1, 13);
            	d2.Print();
            }
            
            public:
            	Date* operator&()
            	{
            		return this;
            	}
            	const Date* operator&()const
            	{
            		return this;
            	}
            private:
            	int _year; // 年
            	int _month; // 月
            	int _day; // 日
            };
            
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]