c++类【终章】
valarray模板类:
valarray<类型名> 变量名;头文件valarray。
私有继承:
有事没事都别用私有继承,有病。以下可以不看。<私有继承-完>
基类的公有成员和保护成员都成为派生类的私有成员,外界不能访问这些继承的成员,但可以通过派生类的公有方法访问。
私有继承实现的是一种has-a关系。和“包含”相比,“包含”将对你作为一个命名的成员对象添加到类中。私有继承将对象作为一个“未被命名”的对象添加到类中。这里要理解“未被命名”意味着什么?意味着如何调用继承的方法。
私有继承,没有被命名,就表示不能使用名称了,只能使用“类名”来调用方法。理解这一点很重要,不然,虽说继承了,但都不知道怎么使用。
初始化:
使用成员列初始化列表语法,使用类名,而不是成员名称(这个和公有继承是一样的)。
访问基类的方法:
使用类名::方法;调用基类方法。(公有继承直接用,不需要用::调用)。包含通过名称.方法调用。
访问基类对象:
通过强制转换,将*this强制转换为基类对象的引用。
访问基类的友元函数
强制软件为基类来调用友元函数,同访问基类对象一样。
总结
有事没事都别用私有继承,有病。
一般用包含。建立has-a关系。
多重继承
建立的是一种has-a的关系。
继承时,默认是私有派生,所以多重继承时,每个基类都要用public限定。
多重继承的两个问题:
1、从多个基类那里,继承了多个同名的方法,咋办?
2、从多个基类那里,继承了同一个类的多个实例,咋办?
虚基类
多重继承导致一个派生类可能继承多个基类(从不同的基类里间接继承过来的),这会导致二义性,因引,引用【虚基类】这个概念,基类定义为虚基类,就会使派生类只继承一个基类对象,消除了二义性。
使用方法:在定义派生类时,在public前(或者后,顺序没关系)增加vitual关键字。注意这个和【虚函数】没有半毛钱的关系,纯粹是因为借用虚这个字而已。
为什么要主动定义为虚基类,才会让派生类消除这种二义性,而不是将虚这种行为定义为默认的规则?主要原因是定义为默认行为,会不经济,同时,还会带来一些问题。
多重继承,在初始化时,会导致一个基类可能通过多个途径传给基类,因此,大多重继承时,限制了通过中间类传递给基类。因此,多重继承时,要修改构造函数,需要直接将参数传给基类构造函数,一般在成员初始化列表里直接显示调用基类构造函数。
方法调用:多重继承,因为二义性,一般调用继承的方法时,尽量用类名进行限定,防止二义性的原因出错。
总结:
尽量不要用多重继承,要用的话,多使用类名进行限定进行调用,减少二义性的出错。
类模板
容器类:用于存储其它对象或数据类型。
模板:提供了一种方法,生成通用的类声明的一种方法。模板提供参数化类型,将类型作为参数传递给接收方来创建类或者函数。
编译器根据模板接收的参数,创建类或函数。
【模板,不是类或函数的定义,他们是c++编译指令】,理解这一点,很重要。
模板的实现:实例化或者具体化。
(函数模板的总结参考这个:C++函数总结-CSDN博客 )。
模板不能单独编译,必须和模板的实例化请求一起使用。因此,一般将模板信息都放在头文件中。
模板类和模板函数还有点不一点,模板类声明时,在类的前面写:template <typename T>,而且在每个成员函数,模板函数的定义前也要写上template <typename T>。和类的声明写在一个头文件里。如下:
类模板使用:
模板名<类型名> 类变量名;
类模板使用场景和普通类一样,可以用作基类,其它类成员,其它模板的参数。
还可以递归使用:Array< Array<int,5> ,10>。一个二维数组。
类模板可以使用多个类型参数,还可以有默认类型:
模板具体化
类模板的具体化,和函数的差不多,也分隐式实例化,显式实例化,显式具体化。
同函数隐式实例化,就是编译器根据声明的对象,自动生成类的定义;
显式实例化,就比较抽象了,不知道也罢。如下,显示实例化,生成了类的定义, 没有名称,没法引用,创建了一个类,但不知道怎么引用用于创建对象。
显式具体化:和函数的差不多,就是指定了一个类型参数。
部分具体化:
模板类,因为允许多具类类型参数,因此,存在对其中某个类型指定具体的类型,这个就叫部分具体化。
类模板的友元
分为3种,非模板友元、约束模板友元、非约束模板友元:
非模板友元:普通的友元,跟模板实例化为具体类型无关联。通过模板名::成员名,访问实例成员。这样的友元函数,模板实例化后,所有的实例都是共用同一个友元函数。
约束模板友元函数:就是友元是个模板函数,先在模板外面定义函数模板,再在类模板里对友元模板函数进行具体化。这种方法定义的友元函数,模板实例化后,每一个实例都有一个专属的友元函数,不共用。
非约束模板友元函数:在类模板内,定义一个模板函数,并将在前面标记为friend。这样,友元函数的每一个具体化,都是都是类具体化的友元。与约束模板友元的区别就是,一个在类模板外面定义,一个在类模板里面定义。
类模板别名:
这个很重要,从模板的定义形式看,然后,模板还可以是别的模板的参数,就会导致声明一个类具体化的时候,要输入很长的字符。导致麻烦,所以,常常起一个短小的意思明确别名。减少打字,也方便看到名称就理解这个类要干啥。
如下:
当然,这还不是最简单的。还有批量的写法。
使用模板提供一系列的别名:
总结:
主要写了,更多的代码重用方法。
讲了实现has-a关系的两种方法。包含和私有继承,从使用简单来说,一般用包含,不要用私有继承,私有继承太繁琐,没必要。
多重继承,为队消除多重继承带来的二义性,引入了虚基类,这个虚和虚函数的虚没有半毛钱的关系,仅仅是同一个字而已。引用虚基类后,多重继承时,通过间接引用同一个基类,造成方法重复的二义性得到解决,虚基类就只会继承一个,不会重复。当然,使用上虚基类,不能通过间接的方法将参数传递给基类了,因此需要重新定义构造函数,将参数直接传给基类。
类模板:创建通用类的方法。