目录
当我们能设计一个规范的类了之后,我们要接着能够做到在不同类之间进行调用及设计。那么本篇通过补充类之间相关的标准语法现象及规范的写法,来进一步完善代码的专业性操作的体系。
static关键字
在一个类中,其包含的成员变量或者成员函数前,都可以进行添加"static"关键字,添加完之后,就成了静态的成员变量或者静态的函数了。
在没有使用static关键字的时候,同样是根据complex类来创建不同的对象,所调用的函数也都是再函数对应的生命周期中创建的,即便创建的形式都是一样的,都是c1,c2,c3,但是,由于this指针的存在,可以创建出来完全不同的对象出来,这是因为this指针在不同的对象中都是不一样的,这也就是为啥编译器可以通过一个构造函数,可以创造并且可以区分清楚多个对象的原因。
在看上图里面,因为this是编译器默认给成员函数配的,如果成员函数把这个指针显式的用出来了,也没事儿(就比如上图标黄的部分),如果没写出来,也没事儿,该加的地方,编译器会提你加上。
而如果加上了static关键字,那么所创建的这个对象所占用的内存空间并不是放在了对应的函数的生命周期当中,并且,加上static的成员或者函数,是独一无二的,不能再像类创建对象一样,一下子创建很多出来,因为这种静态的函数是没有this指针的。
比如,建立一个账户相关的类,那么这个类肯定要可以创建很多个对象——户头,代表每个人的账户,但是,在账户里面有些数据是独一份的,比如:利率,不管人多少,利率都是一样的,那么:
上面的m_rate,代表利率,set_rate代表处理利率的函数,需要强调的是,在类中使用了static创建的变量的时候,这个变量必须要在类外进行初始化,或者称为声明:
double Account::m_rate = 8.0;
调用静态函数有两种方式:1)通过object调用;2)通过class name来调用(上面图展示的很清楚)
下面是C++的一种设计模式,当写出一个类,只希望创建一个对象,这就是下面这种编写方式适合的场景。
其中,把static用在了private区域中去,表明没有任何人可以创建这个类的函数。然后,再创建一个内部函数getInstance,来创建唯一的对象。但这种写法还不是最完美的,就是,如果外界没有用到这个a,那么这个a也是存在的,因为其再private时,就被创建了,所以,进行下改进:
这样一改进后,如歌没有人使用a的时候,是不会被创建的。这是非常好的一种写法。
为什么cout可以接收各种各样类型的数据?
那么将cout的定义代码从标准库中挖出来:
简单说,cout是ostream类所创建的一个对象,从源码可以看出ostream做了好多关于“<<”操作符的重载,正是因为如此,才是cout可以接收那么多类型的数据,并且还可以打印。
类模板(class template)的精髓
在设计复数类型的时候,如果我想我的实部和虚部的数值,不是只限定为double类型,而是想让其适应各种类型,比如:int,float,double等等。那么该怎么办呢?这就用到了类模板,在定义类型的时候不写死成具体的那种类型,而是统一用一个"T"来代替。这样用的时候就可以临时设定想处理的数据类型,来完成适应多种类型的操作了。
函数模板(function template)的精髓
类似于类的模板,函数也可以这样。只不过和类模板的头文件是<typename T>,而函数模板的头文件是<class T>。
但是要注意的是,比如现在的类型是stone,函数模板可以把其对应的类型改为stone,但是,需要注意的是,中间有个环节要用"<"比大小,对应的代码中实际是没有针对stone类型的“<”符号的定义的,那么,你就需要在程序中,有进行对应的定义才行,否则就会报错,应知,函数模板是可以使用的,但也得把其对应的配套函数或者定义给配齐了才行。
C++中的算法,都是这种函数模板的形式。
namespace到底是什么?
上面这个其实就是namespace的样子,"namespace"是一个关键字,后面的"std"是命名的一个名称,然后,把所有的东西,都放在"{}"中,我们就可以说,所有的内容都被包装到了std的命名空间中了。如果在公司,你定义到一些名称,怕跟别人同名,那么你就可以建立一个自己的namespace,把你的定义的名称,放在自己的命名空间中就可以了!
std可以分段来写的,用的时候在写,下面是几种调用的形式:
第一种,等同于你将封装std内容给全部打开,这样写之后std里的所有名称,都可以用!最简便
第二种,是用到std中的什么东西,在专门拿出来,这样做是为了防止代码中用到的命名空间多的话,万一其中有重复命名的名称,就会造成麻烦。稍微麻烦点。
第三种,这种就是最规矩的,用到那个,再把其全名给写出来,这种方式最麻烦。