【C++初阶】之类和对象(中)

2024-03-31 1120阅读

【C++初阶】之类和对象(中)

  • ✍ 类的六个默认成员函数
  • ✍ 构造函数
    • 🏄 为什么需要构造函数
    • 🏄 默认构造函数
    • 🏄 为什么编译器能自动调用默认构造函数
    • 🏄 自己写的构造函数
    • 🏄 构造函数的特性
    • ✍ 拷贝构造函数
      • 🏄 编译器默认生成的拷贝构造函数
      • 🏄 自己写的拷贝构造函数
      • 🏄 拷贝构造函数调用的场景
      • ✍ 赋值运算符重载(也叫拷贝赋值函数)
        • 🏄 运算符重载的引入
          • 💘 前置++和后置++重载
          • 💘 运算符重载函数的调用
          • 🏄 赋值运算符重载
            • 💘 编译器默认生成的赋值运算符重载函数
            • 💘 自己显示写的赋值运算符重载函数
            • ✍ 析构函数
              • 🏄 编译器默认生成的析构函数
              • 🏄 显式写的析构函数
              • 🏄 析构函数的特性
              • 🏄 没有深拷贝,导致二次释放同一空间问题
                • 💘 问题的引入---拷贝构造函数
                • 💘 问题的解决---深拷贝
                • 💘 赋值运算符重载函数的浅拷贝问题
                • ✍ const成员函数
                  • 🏄 const对象访问的规则
                  • 🏄 非const对象访问的规则
                  • ✍ 对普通对象的取地址运算符重载和对const对象取地址运算符重载
                  • ✍ C++默认构造函数提供的机制
                    • 🏄 C++默认构造函数是否提供的情况

                      【C++初阶】之类和对象(中)

                      📃博客主页: 小镇敲码人

                      💞热门专栏:C++初阶

                      🚀 欢迎关注:👍点赞 👂🏽留言 😍收藏

                      🌏 任尔江湖满血骨,我自踏雪寻梅香。 万千浮云遮碧月,独傲天下百坚强。 男儿应有龙腾志,盖世一意转洪荒。 莫使此生无痕度,终归人间一捧黄。🍎🍎🍎

                      ❤️ 什么?你问我答案,少年你看,下一个十年又来了 💞 💞 💞

                      ✍ 类的六个默认成员函数

                      当类为空是编译器也不是什么都不生成,而是会生成六大默认成员函数。

                      【C++初阶】之类和对象(中)

                      我们也可以自己显式把这六个默认成员写出来,这样编译器就会调用我们自己的,而不会调用默认生成的。

                      ✍ 构造函数

                      🏄 为什么需要构造函数

                      我们学习C语言的时候,初始化栈操作需要自己写一个Init函数,但是这样就很麻烦,因为初始化栈之后需要我们显示的去调用Init函数,否则就有可能出现野指针的情况,因为如果是链式的栈,要把next指针初始化为空。

                      🏄 默认构造函数

                      我们构造函数就是为了解决这样的问题,在初始化类的时候,

                      你不需要显示的调用Init函数,编译器会自动的去调用,如果你不去显示的写,

                      编译器会生成一个默认的构造函数。我们来验证一下。
                      
                      class Date
                      {
                      private:
                       int year;
                       int day;
                       int month;
                      };
                      int main()
                      {
                       Date x;
                       return 0;
                      }
                      

                      此时我们写了一个Date类,编译器会给调用它的默认构造函数吗?运行结果:

                      【C++初阶】之类和对象(中)

                      怎么回事呢?x对象的值没有被初始化呀,那是不是代表编译器没有调用默认构造函数呢?其实不然,C++把类型分为自定义类型和内置类型,默认构造函数要做的是,自定义类型去调用它自己的构造函数(如果有的话),内置类型去给一个随机值,那到底是不是这样呢?我们也可以来验证一下。

                      class year
                      {
                      public:
                      	year()
                      	{
                      		std::cout 
                      private:
                      	year y;
                      	int day;
                      	int month;
                      };
                      int main()
                      {
                      	Date x;
                      	return 0;
                      }
                      
                      public:
                      	Date()
                      	{
                      		day = 0;
                      		month = 0;
                      	}
                      	Date(int day = 0,int month = 0)
                      	{
                      	}
                      private:
                      	year y;
                      	int day;
                      	int month;
                      };
                      int main()
                      {
                      	Date x;
                      	return 0;
                      }
                      
                      public:
                      	year()
                      	{
                      		std::cout 
                      public:
                      	Date()
                      	{
                      		day = 0;
                      		month = 0;
                      	}
                      private:
                      	year y;
                      	int day;
                      	int month;
                      };
                      int main()
                      {
                      	Date x;
                      	return 0;
                      }
                      
                      public:
                      	year()
                      	{
                      		std::cout 
                      public:
                      	Date()
                      	{
                      		day++;
                      		month++;
                      	}
                      	void f()
                      	{
                      	}
                      private:
                      	year y;
                      	int day = 0;
                      	int month = 0;
                      };
                      int main()
                      {
                      	Date x;
                      	Date y(x);
                      	return 0;
                      }
                      
                          day = x.day;
                      	month = x.month;
                      	y = x.y;
                      }
                        
                          year++;       // 递增年份  
                          day++;        // 递增日期  
                          month++;      // 递增月份  
                          return *this; // 返回当前对象的引用  
                      }  
                      Date operator++(int) // 后置++  
                      {  
                          Date tmp(*this); // 创建当前对象的副本  
                          ++(*this);       // 递增当前对象(使用前置++)  
                          return tmp;      // 返回递增前的对象的副本  
                      }
                      
                      public:
                      	Date(int year, int month = 2, int day = 1) ://普通的构造函数
                      		year_(year),
                      		month_(month),
                      		day_(day)
                      	{
                      		cout 
                      		cout 
                      		year_ = x.year_;
                      		month_ = x.month_;
                      		day_ = x.day_;
                      		cout 
                      		cout 
                      	x.year_++;       // 递增年份  
                      	x.day_++;        // 递增日期  
                      	x.month_++;      // 递增月份  
                      	return x; // 返回当前对象的引用  
                      }
                      Date operator++(Date&x,int) // 后置++  
                      {
                      	Date tmp(x); // 创建当前对象的副本  
                      	++x;       // 递增当前对象(使用前置++)  
                      	return tmp;      // 返回递增前的对象的副本  
                      }
                      int main()
                      {
                      	Date x(2022);
                      	x++;
                      	++x;
                      }
                      
                      	Date x;
                      	x++;//--operator++(&x,1);
                      	++x;//--operator++(&x);
                      	return 0;
                      }
                        
                          if (this != &x) // 检查自赋值  
                          {  
                              day = x.day;  
                              month = x.month;  
                              year = x.year;  
                          }  
                          return *this;  
                      }
                        
                      	// 检查自赋值,避免不必要的操作  
                      	if (this != &x)  
                      	{  
                      		// 创建一个临时Date对象tmp,并使用参数x来初始化它  
                      		Date tmp(x);  
                        
                      		// 使用std::swap来交换tmp对象的day成员和当前对象的day成员  
                      		std::swap(tmp.day, this-day);  
                        
                      		// 使用std::swap来交换tmp对象的year成员和当前对象的year成员  
                      		std::swap(tmp.year, this-year);  
                        
                      		// 使用std::swap来交换tmp对象的month成员和当前对象的month成员  
                      		std::swap(tmp.month, this-month);  
                        
                      		// 通过上述交换,实际上是将tmp对象(即x的副本)的内容赋给了当前对象  
                      	}  
                        
                      	// 返回当前对象的引用,以支持链式赋值操作  
                      	return *this;  
                      }
                      
                      		year = 0;
                      		day = 0;
                      		month = 0;
                      	}
                      
                      public:
                      	Stack()
                      	{
                      		_capacity = 4;//假设开始的时候给容量设置为4
                      		_top = 0;
                      		_a = (int*)malloc(sizeof(int) * _capacity);
                      		if (_a == nullptr)
                      		{
                      			std::cout 
                      		std::cout 
                      	Stack st1;
                      	Stack st2(st1);
                      	return 0;
                      }
                        
                          // 为栈的底层数组_a分配内存,大小与源栈st的容量相同  
                          _a = (int*)malloc(sizeof(int) * (st._capacity));  
                        
                          // 检查内存是否分配成功  
                          if (_a == nullptr)  
                          {  
                              // 如果分配失败,则输出错误信息并退出程序  
                              std::cout 
                      	Stack st1;
                      	Stack st2;
                      	st2 = st1;
                      	return 0;
                      }
                        
                          // 检查是否自赋值,即当前对象与参数对象是否为同一个对象  
                          if (this != &st)  
                          {  
                              free(_a);//释放之前_a的内存
                              // 创建一个临时Stack对象tmp,并用参数对象st初始化  
                              Stack tmp(st);  
                        
                              // 使用std::swap交换临时对象tmp的底层数组与当前对象的底层数组  
                              std::swap(tmp._a, _a);  
                        
                              // 使用std::swap交换临时对象tmp的栈顶指针与当前对象的栈顶指针  
                              std::swap(tmp._top, _top);  
                        
                              // 使用std::swap交换临时对象tmp的容量与当前对象的容量  
                              std::swap(tmp._capacity, _capacity);  
                          }  
                        
                          // 返回当前对象的引用,支持链式赋值操作  
                          return *this;  
                      }
                      
                      public:
                      	Date()
                      	{
                      		year = 2024;
                      		month = 1;
                      		day = 1;
                      	}
                      	void f() const
                      	{
                      		this-year = 1;
                      	}
                      private:
                      	int year;
                      	int month;
                      	int day;
                      };
                      int main()
                      {
                      	Date x;
                      }
                        
                          return this;  
                      }
                      // const成员函数的取地址运算符重载  
                      // 返回当前对象的const地址  
                      const Date* operator&() const  
                      {  
                          return this;  
                      }
                      
VPS购买请点击我

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

目录[+]