-
1.c++类里默认生成的成员函数(特性:用户没有定义,编译器自动生成)
- 构造函数:
- 5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成.
- 6.用户自定义的构造函数可以有参数也可以没有参数,无参的构造函数和全缺省的构造函数都称为默认构造函数(编译器自己能调用),并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写,编译器默认生成的构造函数,都可以认为是默认成员函数。
- 构造函数{...}里的叫赋值,不是初始化,初始话格式:例如Date (int year,int month,int day):_year(year),_month(month),_day(day){...}这个是在没进入构造函数之前完成的,(初始化格式如果不写,编译器自己会加上)
- 普通类型的成员变量出不初始化都无所谓,但是引用,const,其他自定义类型(该类没有默认构造函数)必须初始化.为什么自定义类型没有默认构造函数就必须初始化呢?因为,自定义的构造函数如果不是全缺省的,编译器调不出来,编译器只会掉没有参数的构造函数,全缺省的函数即使调用的时候不加参数,编译器也能调...不是全缺省的就得根据自己写的构造函数自己传值,要自己传值,所以编译器掉不了,得自己调.
- 成员有多个,但是构造函数的参数只有一个例如Date(int year),导致Date d=2022;这个语句与单参的构造函数配合就是对的,过程:2022调用单参的构造函数,数字转成了临时对象,拷贝给d,考完就析构...这个可读性不高,不建议,用explicit修饰构造函数,构造函数就没有转化的能力了,上述的操作就会报错
- 析构函数
- 析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作,例如释放内存等等.
- 3. 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
- 4. 对象生命周期结束时,C++编译系统系统自动调用析构函数
- 注意:如果类里没有动态开辟的资源,编译器自动调用自己生成的析构函数即可,如果类里有动态开辟的一些资源,那么需要程序员手动生成析构函数,由编译器调用.类里由资源管理的情况如果不手动析构会造成内存泄漏
- 拷贝构造函数 例:Date(const Date&d)(拷贝构造也属于构造,也有初始化列表)
- 2. 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
- 3. 若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝。
- 浅拷贝:对于类成员里只有int ,char,double,等类型的数据,编译器生成的拷贝构造函数或者自己写的函数不存在问题(也就是上述说的浅拷贝),但是如果类成员里有指针类型的成员,经过拷贝构造函数之后,两个对象里的指针就指向了同一块内存空间.这个没有问题,但是,如果在最后调用了析构函数,当释放了一个对象里的指针之后,另一个对象里的指针就指向了一块非法空间,这个对象销毁时再释放这个指针就会出错.(对于这类问题需要)
- 拷贝构造函数的参数一定要是引用的形式,如果以值传递,就会无限拷贝下去.类里的传参如果是以值的形式传,会由实参到形参的一次拷贝,返回一个对象,也会调用一次拷贝构造.
- 赋值运算符重载的统一格式 " (返回值) operator+[要重载的运算符](参数)"(加返回值是为了能够满足连续赋值)
- 一个类如果没有显式定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝。
- 赋值运算符重载编译器生成的同样也是浅拷贝,不能解决拷贝指针引发的问题..
- 赋值运算符必须重载成成员函数,如果不是在类里生成的,那么编译器会给类生成一个默认的函数,两个就冲突了
-
2.类里的注意事项 - const
- const修饰的对象是不能被改变的,任何时候都不能修改,但是要拿对象调用类里函数,如果在函数里修改了const修饰的对象就不满足语法,为了安全起见,定义专门为const类型对象服务的函数.在函数定义后面加const,这样更安全.
- 全局变量可以计数,但是不安全,选择用static修饰得静态成员变量
- static 在类里创建的变量是静态变量不属于某一个对象,static在类里创建的函数也不属于某一个对象,这个函数是没有this指针的,所以可以不用通过对象.函数名/变量名的方式进行访问.通过 类名:: 访问
- 静态成员变量的建立,注意:定义要加上作用域限定.在类外初始化..因为_count还是私有的所有要建立一个静态成员函数用来获取_count的值
- 注意:静态成员变量不能在构造函数里赋值和初始化,这个变量不属于某一个对象
- 获取静态成员变量得值可以用静态成员函数,Date::(函数名)或者d.(函数名)也可以不用静态成员函数,用普通的类里的函数,只能用d.(函数名)...
- 赋值运算符和拷贝构造的区别:例如Date d1(d2),Dat2 d1=d2,这俩都是拷贝,因为d1还没有创建成功,所以是拷贝构造,赋值就是两个都已经创建成功了
- 被mutable修饰的成员变量.即使对象被const修饰,这个成员变量也能改变
- <<运算符重载,必须在类外重载.应用:在main函数里直接调用cout打印成员变量,不需要调用类对象里的打印函数
- 不是类里的函数,不能在类外访问类里的私有的成员变量,所以有了友元函数,在类里把这个函数声明一下就行了
?
|