一、 什么是构造函数数是干什么嘚
// 特点:以类名作为函数名无返回类型
// 如果创建一个类你没有写任何什么是构造函数数,则系统会自动生成默认的无参什么是构造函数数,函数为空什么都不做 // 只要你写了一个下面的某一种什么是构造函数数,系统就不会再自动生成这样一个默认的什么是构造函数数如果希望有一个这样的无参什么是构造函数数,则需要自己显示地写出来 //
一般什么是构造函数数(也称重载什么是构造函数数) // 一般什么是構造函数数可以有各种参数形式,一个类可以有多个一般什么是构造函数数前提是参数的个数或者类型不同(基于c++的重载函数原理) // 创建對象时根据传入的参数不同调用不同的什么是构造函数数
// 将对象c中的数据成员值复制过来
// 类型转换什么是构造函数数,根据一个指定的类型的对象创建一个本类的对象
//需要注意的一点是,这个其实就是一般的什么是构造函数数但是对于出现这种单参数的什么是构造函数數,C++会默认将参数对应的类型转换为该类类型有时候这种隐私的转换是我们所不想要的,所以需要使用explicit来限制这种转换
// 等号运算符重載(也叫赋值什么是构造函数数) // 注意,这个类似复制什么是构造函数数将=右边的本类对象的值复制给等号左边的对象,它不属于什么昰构造函数数等号左右两边的对象必须已经被创建 //
若没有显示的写=运算符重载,则系统也会创建一个默认的=运算符重载只做一些基本嘚拷贝工作 // 首先检测等号右边的是否就是左边的对象本身,若是本对象本身,则直接返回 // 复制等号右边的成员到左边的对象中 //
把等号左边的對象再次传出 // 然后运行 a= ( b=c的返回值,这里应该是复制c值后的b对象)
下面使用上面定义的类对象来说明各个什么是构造函数数的用法:
// 调用了无参什么是构造函数数数据成员初值被赋为0.0 // 调用一般什么是构造函数数,数据成员初值被赋为指定值 // 也可以使用下面的形式 // 把c3的数据成员的徝赋值给c1
// 由于c1已经事先被创建故此处不会调用任何什么是构造函数数 // 只会调用 = 号运算符重载函数 // 调用类型转换什么是构造函数数 //
系统首先调用类型转换什么是构造函数数,将5.2创建为一个本类的临时对象然后调用等号运算符重载,将该临时对象赋值给c1 // 调用拷贝什么是构造函数数( 有下面两种调用方式) Complex c4 = c2; // 注意和 =
运算符重载区分,这里等号左边的对象不是事先已经创建故需要调用拷贝什么是构造函数数,参数为c2 //这┅点特别重要这儿是初始化,不是赋值其实这儿就涉及了C++中的两种初始化的方式:复制初始化和赋值初始化。其中c5采用的是复制初始囮而c4采用的是赋值初始化,这两种方式都是要调用拷贝什么是构造函数数的
// 将对象c中的数据成员值复制过来
为什么函数中可以直接访問对象c的私有成员?
答:(网上)因为拷贝什么是构造函数数是放在本身这个类里的而类中的函数可以访问这个类的对象的所有成员,當然包括私有成员了
2. 挑战题,了解引用与传值的区别
// 下面函数执行过程中各会调用几次什么是构造函数数调用的是什么什么是构造函數数? // 下面这条语句会出错吗
答:为了便于看什么是构造函数数的调用效果,我将类重新改一下添加一些输出信息
下面是程序运行结果:第一次运行结果
四、附录(浅拷贝与深拷贝)
上面提到,如果没有自定义复制什么是构造函数数则系统会创建默认的复制什么是构造函數数,但系统创建的默认复制什么是构造函数数只会执行“浅拷贝”即将被拷贝对象的数据成员的 值一一赋值给新创建的对象,若该类嘚数据成员中有指针成员则会使得新的对象的指针所指向的地址与被拷贝对象的指针所指向的地址相同,delete该指针
时则会导致两次重复delete而絀错下面是示例:
【浅拷贝与深拷贝】
//在堆中开辟一个内存块存放pN所指的字符串 //如果m_pName不是空指针,则把形参指针pN所指的字符串复制给它 // 系统创建的默认复制什么是构造函数数只做位模式拷贝
//使两个字符串指针指向同一地址位置 // 结果导致 man 和 woman 的指针都指向了同一个地址 // 下面洎己设计复制什么是构造函数数,实现“深拷贝”即不让指针指向同一地址,而是重新申请一块内存给新的对象的指针数据成员
// 用运算苻new为新对象的指针数据成员分配空间 // 则新创建的对象的m_pName与原对象chs的m_pName不再指向同一地址了
下面讨论一个重要问题是:什么是构造函数数的显式调用
大家看看下面这段代码的输出结果是什么这段代码有问题么?
输出结果中m_a是一个不确定的值,因为没有被赋初值m_b 为2
在调用CTest()函數时,实际上是创建了一个匿名的临时CTest类对象CTest()中赋值 m_a = 1 也是对该匿名对象赋值,故我们定义的myTest的m_a其实没有被赋值说白了,其实什么是构慥函数数并不像普通函数那样进行一段处理而是创建了一个对象,并 且对该对象赋初值所以显式调用什么是构造函数数无法实现给私囿成员赋值的目的。
这个例子告诉我们以后代码中千万不要出现使用一个什么是构造函数数显式调用另外一个什么是构造函数数这样会絀现不确定性。其实一些初始化的代码可以写在一个单独的init函数中然后每一个什么是构造函数数都调用一下该初始化函数就行了。
代码祐边显示调用CTest()是否依然会产生一个匿名的临时对象a,然后将该匿名的临时对象a的地址赋给指针p? 如果是这样的话出了func函数后,临时对象a昰否会被析构? 那指针p不成为了野指针了你能解释这个问题么?
答:我实验的结果是不会产生临时对象a直接将产生的对象指针赋给了p