赞
踩
感谢大佬的光临各位,希望和大家一起进步,望得到你的三连,互三支持,一起进步
类的默认成员函数,默认成员函数就是用户没有显式实现,编译器会自动生成的成员函数称为默认成员函数。一个类,我 们不写的情况下编译器会默认生成以下6个默认成员函数。
因为前面对构造函数进行过了讲解,这里只做补充
注意:构造函数就是替代了以前C语言中的初始化,对象实例化时系统会自动调用对应的构造函数,构造函数是可以重载的
默认构造函数概念:1.无参构造函数,2.全缺省的,3.不写构造时编译器默认生成的。这三个函数有且只能有一个存在,总结:不传实参数就可以调用的构造叫做默认构造
对于编译器默认生成的构造,对内置类型成员变量初始化没有要求,但对于自定义类型成员变量,会调用这个成员变量的默认构造函数,如果这个成员变量没有构造函数就会报错,这时候就用初始化成员列表。
那么什么是内置类型和自定类型呢?C++把类型分为两类,内置类型和自定义类型,内置类型就是int,char,float,指针这种,自定义类型就是类,结构体,class,struct
这句话不是很好理解,我们来举个例子,方便理解一下
例子:
这段代码运行来是没有任何问题的,但是如果修改就会有问题
- #include<iostream>
- using namespace std;
- class Date
- {
- public:
-
- Date()
- {
- _year = 1;
- _month = 1;
- _day = 1;
- }
-
- Date(int year, int month, int day)
- {
- _year = year;
- _month = month;
- _day = day;
- }
- void Print()
- {
- cout << _year << "/" << _month << "/" << _day << endl;
- }
- private:
- int _year;
- int _month;
- int _day;
- };
- int main()
- {
- Date d1;
- Date d2(2025, 1, 1);
- Date d3();
- return 0;
- }
我们如果把第二个构造函数给注释调的话,那么程序就会出错,因为我第二个对象创造的时候没有构造函数给他调用,所以就会报错
同理,如果我把第一个注释掉的话也会报错,因为第一个和第三个没有对应的构造函数
那如果我把两个构造函数全部注释掉可以吗?系统不是有一个默认的吗?系统会帮我们生成一个没有参数的无参构造函数,那么如果想要程序运行成功的话,就要把第二个对象也注释
那么默认的构造函数到底什么时候用呢?或者是说我什么时候要写构造函数什么时候不写呢?我们之前学过一个用栈来构造队列,如果把它用C++来写的话
- class MyQueue
- {
- public:
- private:
- Stack pushst;
- Stack popst;
- };
编译器默认生成MyQueue的构造函数调用了Stack的构造,完成了两个成员的初始化
如果我的成员对象是有构造函数的时候,他会先调用成员对象的构造函数,这种情况下如果帮我初始化了的话,我就不需要初始化了,我就不需要调用了,总结:大多数情况下,构造函数都需要我们自己来实现,少数情况下不需要
析构函数不想做太多的补充,跟之前一样,析构函数对应着就是C语言中的销毁,注意:自定义类型的成员也会调用它的析构,也就是说自定义类型成员无论什么情况都会自动调用他的析构函数。
拷贝构造函数是类与对象中的一个难点,拷贝构造函数是构造函数的一个重载,他有一个特别的地方,就是第一个参数必须是自身类型的引用,不然会引发无穷递归调用的报错
C++语法规定,传值传参会掉用拷贝构造函数。
我们之前讲过引用的本质是常量指针,所以说,如果不是引用的话,他就会无限递归
若未显示定义拷贝构造函数,编译器会自动生成一个拷贝构造函数,自动生成的拷贝构造对内置类型成员变量会完成浅拷贝,对自定义类型的成员变量会调用它的拷贝构造函数
这个地方和前面的有所差距,比如说我们再用那个站来实现队列的例子,这个地方就不能用系统自己的拷贝构造了
- int main()
- {
- Stack st1;
- st1.Push(1);
- st1.Push(2);
- // Stack不显示实现拷贝构造,用自动生成的拷贝构造完成浅拷贝
- // 会导致st1和st2里面的_a指针指向同⼀块资源,析构时会析构两次,程序崩溃
- Stack st2 = st1;
- MyQueue mq1;
- // MyQueue自动生成的拷贝构造,会自动调用Stack拷贝构造完成pushst/popst
- // 的拷贝,只要Stack拷贝构造自己实现了深拷贝,他就没问题
- MyQueue mq2 = mq1;
- return 0;
- }
这里我们在前面的类与对象中讲了浅拷贝和深拷贝的问题,在这个地方就不多做解释了。
- Date(const Date& d)
- {
- _year = d._year;
- _month = d._month;
- _day = d._day;
- }
赋值运算符重载就是把一个对象复制给另一个对象。拷贝能分两种,一种是赋值重载拷贝,一种是拷贝构造,那到底怎么区分呢?赋值重载就是两个都存在的对象进行赋值,而拷贝构造是把初始化的对象去赋给没有初始化的对象。
- int main()
- {
- Date d1(2024, 7, 5);
- Date d2(2024, 7, 6);
- //赋值重载拷贝
- operator==(d1, d2);
- d1 == d2;
- //拷贝构造
- Date d3(d2);
- Date d4 = d2;
- return 0;
- }
C++规定类类型对象使用运算符时,必须转换成调用对应运算符重载,若没有对应的运算符重载,则会编译报错。运算符重载是具有特名字的函数,他的名字是由operator和后⾯要定义的运算符共同构成。和其他函数一样,它也具有其返回类型和参数列表以及函数体。
- bool operator==(const Date& d1, const Date& d2)
- {
- return d1._year == d2._year
- && d1._month == d2._month
- && d1._day == d2._day;
- }
.* :: sizeof ?: . 注意以上5个运算符不能重载。
重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,无法很好的区分。
C++规定,后置++重载时,增加一个int形参,跟前置++构成函数重载,方便区分。重载<<和>>时,需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第一个个形参位置,第一个形参位置是左侧运算对象,调用时就变成了 对象<<cout,不符合使用习惯和可读性。重载为全局函数把ostream/istream放到第一个形参位置就可以了,第二个形参位置当类类型对象。
这个地方不做过多的讲解,到时候会专门来出一个日期类的实现,就专门运用这个赋值运算符重载来实现的。
将const修饰的成员函数称之为const成员函数,const修饰成员函数放到成员函数参数列表的后面。 • const实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。const修饰Date类的Print成员函数,Print隐含的this指针由 Date* const this 变为 const Date* const this
- class Date
- {
-
- public:
- Date(int year = 1, int month = 1, int day = 1)
- {
- _year = year;
- _month = month;
- _day = day;
- }
- // void Print(const Date* const this) const
- void Print() const
- {
- cout << _year << "-" << _month << "-" << _day << endl;
- }
- private:
- int _year;
- int _month;
- int _day;
- };
- int main()
- {
- //这里非const也可以调用const成员函数这是⼀种权限的缩⼩
- Date d1(2024, 7, 5);
- d1.Print();
- const Date d2(2024, 8, 5);
- d2.Print();
- return 0;
- }
取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载,⼀般这两个函数编译器自动生成的就可以够我们用了,不需要去显示实现。除非⼀些很特殊的场景,逼如我们不想让别人取到当 前类对象的地址,就可以自己实现⼀份,胡乱返回⼀个地址。
- class Date
- {
- public:
- Date* operator&()
- {
- return this;
- // return nullptr;
- }
- const Date * operator&()const
- {
- return this;
- // return nullptr;
- }
- private:
- int _year;
- int _month;
- int _day;
- };
用static修饰的成员变量,称之为静态成员变量,静态成员变量⼀定要在类外进行初始化,因为不存在对象中,存放在静态区用static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针,静态成员也是类的成员,受public、protected、private 访问限定符的限制。
- class A
- {
-
- static int GetACount()
- {
- return _scount;
- }
- private:
- // 类⾥⾯声明
- static int _scount;
- };
- // 类外⾯初始化
- int A::_scount = 0;
- int main()
- {
-
- return 0;
-
- }
'运行
描述
求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
数据范围: 0<
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/994405
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。