构造函数

1.构造基本概念

1.是成员函数的一种,名字与类名相同,可以有参数,不能有返回值(void也不行)

作用是对对象进行初始化,如给成员变量赋初值

2.如果定义类是没写构造函数,则编译器生成一个默认的无参数的构造函数。(不做任何操作

如果定义了构造函数,则编译器不生成默认的无参数的构造函数。

3.对象生成时构造函数自动被调用。对象一旦生成,就再也不能在其上执行构造函数。

4.一个类可以有多个构造函数。

5.为什么要构造函数?

1.构造函数执行必要的初始化工作,有了构造函数,就不必专门在写初始化函数,也不用担心忘记调用初始化函数。

2.有时对象没有被初始化就使用,会导致程序出错。

构造函数_第1张图片构造函数_第2张图片

2.构造函数在数组中的使用

构造函数_第3张图片

3.复制构造函数

1.只有一个参数,即对同类对象的引用

形如形如类名::类名(类名&)类名::类名(const 类名&)二者选一,后者能以常量对象做参数。(常选后者

如果没用定义复制构造函数,那么编译器生成默认复制构造函数。

默认的复制构造函数完成复制功能。

构造函数_第4张图片

如果定义自己的复制构造函数,则默认的复制构造函数不存在。

构造函数_第5张图片

不允许有形如X::X(X)的构造函数

构造函数_第6张图片

编写复制构造函数

当我们自己编写了复制构造函数之后,编译器将不再生成默认的复制构造函数。如下面的例子所示:

构造函数_第7张图片

对于上面的类,在复制构造函数被调用的时候将完成复制的工作,并且向控制台输出调用复制构造函数!!,假设我们有如下的初始化:

构造函数_第8张图片

得到结果是:

构造函数_第9张图片

错误用法

复制构造函数的参数一定要是对同类对象的引用,不能为其它的。构造函数_第10张图片

如上所示,我们错误的将参数Complex& c写为了Complex c,此时我们的编译将无法通过

总之,复制构造函数的参数一定要是同类对象的引用.

4.复制构造函数起作用的三种情况

1.用一个对象来初始化正在构造的对象变量

当我们用同类的一个对象去初始化另一个对象时,会导致构造函数被调用。

构造函数_第11张图片

2.函数的参数为类的对象时

如果某函数有一个参数是类的对象,那么该函数被调用时,该类的复制构造函数将被调用。

构造函数_第12张图片

其中我们定义了一个函数fun(Complex c),其参数为一个Complex对象,当我们在调用fun(Complex c)的时候,形参c将被初始化,此时将调用复制构造函数完成初始化工作,产生如下的输出:调用复制构造函数!!

需要注意的是,如果函数的参数为对象的引用或常引用时,将不会导致构造函数被调用,如下所示:void fun(Complex &c){}

3.函数的返回值是类的对象时构造函数_第13张图片

函数fun()返回一个Complex类的对象,在调用fun()函数时会导致复制构造函数被调用。

优化

当对象作为函数参数,在对函数进行调用时会调用复制构造函数对形参进行初始化工作,此时会产生额外的开销,我们可以将函数的参数写为对象的引用来避免额外的开销,如果担心对象的值在函数中会被改变,我们也可以用常引用的方式。

Complex fun(Complex c){}

我们可以写成:
Complex fun(Complex& c){}
Complex fun(const Complex& c) {}

5.类型转换构造函数

定义:1.有且仅有一个参数

2.参数是基本类型

3.转换构造函数的参数类型是其它类型

1,类型转换函数主要功能就是做类型转换,类型转换是将一个数据从 A 类型转换  到 B 类型,有隐式类型转换和强制类型转换两种;

构造函数_第14张图片

输出结果:

构造函数_第15张图片

ui 为 unsigned int 类型, i 为 int 类型,将两者进行相加编译器会进行隐式的类型转换,全部变成 unsigned int 类型,所以最后的运行结果是正数。

构造函数_第16张图片

这里其实发生了我们该才说的利用了转换构造函数,把6转换成Test(6),而这样写就会产生一临时对象,所以就可以进行复制了;但是在现在的技术发在中,肯定是不希望出现这种要人去防止这隐式转换;所以在c++中有了新技术来防止出现隐式转换:

工程中通过explicit关键字杜绝编译器的转换尝试

转换构造函数被explict修饰只能进行显示转换(强制类型转换)

你可能感兴趣的:(C++,c++)