一、从上一章class声明中的补充
说设计一个 class 要有一个声明,其实也有一个模板的概念。其中在 class body 中,有些函数在 class body 中直接定义,也有一些在 body 之外定义也没有问题
二、inline(内连)函数
这里提到一个inline的概念,那么当函数在 class 的本体里面这样定义,就形成了一种 inline ,在外部定义就不会产生 inline 。
inline 类似于宏,在C中的概念,是一种特性。我们说Function写成inline最好,但是有些Functions即使写成inline,编译器有些也不以为是inline。如果Functions太复杂,就无法认为inline , 这是由编译器来决定的。
1- { }
2- complex& operator += (const complex&);
3-
4- double real() const {return re ; }
5- double imag() const {return im ; }
在上述代码中 real()与imag()就属于inline的方式,但是具体结果是否为inline,是由编译器决定。函数我们说1、4、5这样的,函数在class中定义完成,那么就成为了inline的侯选项,但注意此时还不是inline。
Tips:2中在下面并没有定义,在外部,下方就会看到。
三、access level(访问级别)
在class body中我们可以区分为几大段,用关键字来区分,那么这几个块就是访问级别。如下面这两种(上述代码中):
public:
private:
pbulic:公开,外部可以看到(Functions分两种,内部使用和外部使用,内部使用也可以放在private:中)
private:私有,只在class中能够看到。(Data数据部分,应该封装起来)
其实有第三种,protected:(保护的),这里不提到。
我们说这些段落可以任意交错,都可以的。那么下面是正确的使用方法:
{
1- complex c1 (2,1);
2- cout << c1.real();
3- cout << c1.imag();
}
其中 1- 就是创建一个对象,调用其构造函数。下面的cout 就是利用real()与imag()函数输出实部和虚部。
下面的错误在于,创建的c1对象我们直接cout它的re(实部)和im(虚部),那么在(二)C++头文件与类的声明中的代码可以看到,re(实部)与im(虚部)实际上是在private:中,我们上面说这个private:中放的是数据。
{
1- complex c1 (2,1);
2- cout << c1.re;
3- cout << c1.im;
}
我们说数据,要在同类中进行处理,一个读一个取,利用functions,不能直接在外部对Data进行取值。
四、constructor(ctor,构造函数)
我们说当你创建一个对象,一个东西,constructor(构造函数)会被调用起来
{
complex c1(2,1);
complex c2;
complex& p = new complex(4);
……
}
这里就是创建一个数c1,其 re 值为2,im 值为1。创建一个c2,没有参数,类似于数学0+0i。第三种动态创建一个复数,得到了一个ptr(指针)。
1- class complex
2- {
3- public:
4- complex (double r=0,double i=0 )
5- : re(r),im(i)
6- { }
7- }
4- 中的函数名称 complex()一定要跟上面的class complex这个类相同,才叫做构造函数。
对于函数complex()中,可以有参数,这里复数设置就是实部与虚部两个参数,这些参数是可以有值的,叫做 default argument(默认实参)。
那么我们说在创建对象时,像 c1 指定参数的,就使用指定参数,像 c2 未使用指定参数的就用default argument(默认实参)。这个特性并不是构造函数的特性。
构造函数还有另一种特性,没有返回类型。因为构造函数是用来创建对象,来创建class中complex类的,所以不必写出。
里面具体要做什么,是自己来设计的。这里就是将r 放到 re 中,i 放到 im中,这个动作是在 6- 这个大括号中利用赋值的写法来完成的。但是我们要采用更好的写法,利用构造函数特别的语法(5-),叫做initialization list(初值列,初始列)。当然4-与5- 也可以写成一行。实际上同 6-{}中是一样的意义。
简单理解:一个变量,东西,数值的设定有两个阶段,初始化+赋值。初始化为 5-,赋值为6-,忽略5-就是忽略了初始化这个阶段。
complex {double r = 0,double i = 0}
{re = r ;im = i;}
上述就是将assignments(赋值)这个操作放到了6-中 忽略了5- 。
对应构造函数中还有一个析构函数,这里不提到。上述这种class complex 就是说过的不带指针的,类中大部分不用到析构函数。
五、ctor(构造函数)可以有很多个-overloading(重载)
现实中我们设计某个类,等待外界创建命令,创建命令格式会有多种想法,那么我们这里就将相同函数名称,但有多个构造函数,就称为overloading(重载)。
1- { }
2- complex& operator += (const complex&);
3-
4-1 double real() const {return re ; }
4-2 void real(double r) { re = r;}
5- double imag() const {return im ; }
4-1与4-2就是典型的 overloading ,那么在编译器中实际中的名称不同,可能是这一种:
?real@Complex@@QBENXZ
?real@Complex@QAENABN@Z
刚刚说构造函数常常会发生 overloading 的现象,那么我们说这里进行:
1- class complex
2- {
3- public:
4-1 complex (double r=0,double i=0 )
5- : re(r),im(i)
6- { }
4-2 complex () : re(0),im(0) { }
7- }
这里我们说4-1 与 4-2 发生了overloadding,但实际上这是一种错误,因为在4-1中有了默认参数。例如:
{
complex c1;
complex c2();
}
这里创建两个c1与c2,都没有参数,那么编译器并不知道取哪一个complex()用来处理你创建的对象,会发生冲突。
下一章:(四)参数传递与返回值