类和对象(中)

1.构造函数

(1)是一个特殊的成员函数,用于对成员变量的初始化,特点函数名和类名相同同时不用写返回值.

演示:

(2)可以进行重载,符合函数重载的所有要求与特点.

(3)无参构造函数,全缺省构造函数,编译器自动生成的构造函数叫做默认构造函数且这三种构造函数只能存在一个,编译器在类类型变量创建完后会自动调用默认构造函数.

(4)有参函数与无参函数的初始化差距

有参时

无参时

(5)没有显性定义构造函数时,编译器会自动生成一个默认构造函数,但有显性构造函数时,编译器就不会自动生成一个了.因此当只有一个含参构造函数且没有调用初始化列表时,程序会报error.

(6)编译器默认的构造函数是不会对类内部的内置类型成员进行初始化的(有部分编译器会进行初始化,但是从整体角度而言,无视即可),但是对于类类型成员会调用它内部的默认构造函数,没有会直接error.因此绝大多数情况都需要我们自己设计默认构造函数.

(7)对一个含有类类型成员的类的构造函数(函数中没有直接调用成员类的构造函数),可以发现编译器在进入构造函数内部之前,会先进类类型成员变量的默认构造函数中,再会回来继续走当前构造函数代码.

2.析构函数

用途:类似于stack中的destroy,是用于清理释放资源空间的,如动态内存开辟.

(1)依旧没有返回值,但这里还没有参数函数名是(~函数名)

(2)一个类只能有一个析构函数,没有显性定义时,编译器会自动生成一个默认构析函数

(3)当该类类型对象的生命周期结束时,编译器会自动调用构析函数.从此处看能发现c++比c语言方便的多,不用自己调用destroy函数,减少了内存泄漏的可能.

(4)和构造函数相似,编译器自动生成的构析函数是不会处理内置类型的,自定义类型会调用其自己的析构函数.因此析构函数大多数时候都要我们自己写.特别是有内存泄漏可能的类类型.

(5)同一类类型的变量,除了全局变量和被static修饰的变量之外,后创建的先析构(类似于栈的特点)然后是static的析构,最后是全局的析构.

原因:全局变量是最先创建的,然后是局部变量,局部变量中由于static的有常型,故会放在最后(在全局前面)析构.

3.拷贝构造函数

用途:用同一个类类型变量来初始化一个变量.

(1)拷贝构造函数的本质构造函数的函数重载.当一个构造函数有且只有第一个参数是类类型变量的引用同时其它参数都为内置类型并且都有缺省值时,其就被定义为拷贝构造函数.

(2)为什么不能用值拷贝而必须用引用?

首先要明白c++在调用函数时如果参数是传值传参同时为类类型变量的话,在给形参赋值前会掉用一次拷贝构造函数形成临时对象,然后用该临时对象中的值给形参赋值(其实这种情况在传值返回时也会存在).

假设有下面这种情况:

现在我们要调用love函数,实参赋给形参d之前要调用一次赋值拷贝构造,而由于赋值拷贝构造中也是形参,因此又要去调用拷贝构造.也就是变成了为了调用拷贝构造因此去调用拷贝构造的死循环情况.这种情况下的最好方法就是拷贝构造函数用引用.

const的使用是因为该函数不需要修改d,因此加上.

(3)当我们没有显性构造拷贝构造函数时,编译器会自动生成一个拷贝构造函数.这个默认生成的拷贝构造函数会对内置类型进行浅拷贝(一个字节一个字节的拷贝),对自定义类型会调用其内部的拷贝构造函数.

浅拷贝在面对类似于有动态内存开辟空间的类类型时容易出问题.

如图,gal2被gal1以浅拷贝的形式拷贝,使得二者的arr指针指向了同一块空间,当析构函数进行空间释放时,同一块空间会被释放两次,造成程序error.因此在有动态内存开辟的类类型变量时,必须采用深拷贝即自己写拷贝构造函数.

在自己写了拷贝对象后,二者在内容上相同,但指向两块空间了.

通过这里能发现c语言的一个问题:c语言传值传参都是浅拷贝,因此再传含有动态内存开辟的自定义类型时的传值传参,即使是使用形参,也可以通过形参修改实参中的数据,甚至在释放形参空间时实际是释放了实参的空间,产生严重后果.

这两种都算是拷贝构造.

返回引用不要使用函数中的局部变量,会造成非法访问.

5.const 函数

首先对const指针类型进行回顾

const int* p 是指不能通过解引用修改指针内容

int*const p 是指不能改变指针指向

const 函数是用于给this指针加前置从const的.const也只可以用于修饰成员函数.

this指针的类型是 variable*const this.

const 放在函数参数的后面.在既有声明也有定义时,const两处都要放.

用法:

const galgame gal1(29, 10);

在这种情况下,gal1无法调用print

因为print中的this为galgame*const this

而上面的调用传地址时的类型是const galgame* this

存在内存放大的问题.

const修饰后就可以了.

为了防止类似的情况发生,在不用对*this的内容修改的前提下,最好都加上一个const修饰.

6.取地址运算符重载

二者由于const的差别,构成函数重载.正常情况下编译器会帮我们生成,故不用写.

相关推荐
Max_uuc1 小时前
【架构心法】炸毁巨石阵:从单体巨兽到微内核 (Microkernel) 插件化架构的 Qt C++ 工业软件演进
c++·qt·架构
「QT(C++)开发工程师」1 小时前
# [特殊字符] Day 1:Qt 信号槽原理深入 - 核心学习笔记
c++·qt
Mr YiRan7 小时前
C++面向对象继承与操作符重载
开发语言·c++·算法
额,不知道写啥。13 小时前
HAO的线段树(中(上))
数据结构·c++·算法
LYS_061814 小时前
C++学习(5)(函数 指针 引用)
java·c++·算法
ADDDDDD_Trouvaille14 小时前
2026.2.21——OJ95-97题
c++·算法
Once_day15 小时前
C++之《程序员自我修养》读书总结(4)
c语言·c++·编译和链接
tod11316 小时前
C++核心知识点全解析(二)
开发语言·c++·面试经验
载数而行52017 小时前
算法系列2之最短路径
c语言·数据结构·c++·算法·贪心算法