第14章 C++中的代码重用

      公有继承是实现代码重用的机制之一,但并不是唯一的机制。本章介绍包含、私有继承和保护继承,他们用于实现has-a关系,即新的类包含另一个类的对象。而公有继承实现的是is-a关系。

1.包含对象成员的类

      包含(containment),又叫组合(composition)或层次化(layering).

      Valarray类简介:https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/1.jpg

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/2.jpg

       student类范例:

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/3.jpg

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/4.jpg

2.私有继承

      使用私有继承后,新版本的构造函数将使用成员初始化列表句法(同公有继承一样),而不是像包含那样用成员名来标识。

       使用包含时将使用对象名来调用方法,而使用私有继承时将使用类名和作用域解析操作符来调用方法。

       使用作用域解析操作符可以访问基类的方法,但如果要使用基类对象本身,该如何做?包含里面Name()方法返回string对象成员name;但使用私有继承时,该string对象没有名称。答案是用强制类型转换,将Student对象转换为string对象。

        怎样访问基类的友元函数呢。用类名显式地限定并不适合,因为友元不属于类。不过可以显式地转换为基类来调用正确的函数。在下面,引用stu不会自动转换为string引用,根本原因是:私有继承中,在不进行显式类型转换的情况下,不能将指向派生类的引用或指针赋给基类引用或指针。

       修改后的student类:

      通常,应使用包含来建立has-a关系;如果新类需要访问原有类的保护成员,或需要重新定义虚函数,则应使用私有继承。

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/5.jpg

3.保护继承

      使用保护继承时,基类的公有成员和保护成员都将成为派生类的保护成员。和私有继承一样,基类的接口在派生类中也是可用的,但在继承层次结构之外是不可用的。当从派生类派生出另一个类时,私有继承和保护继承之间的主要区别就呈现出来了。使用私有继承时,第三代类将不能使用基类的接口,这是因为基类的公有方法在派生类中将变为私有方法;使用保护继承时,基类的公有方法在第二代中将变成受保护的,因此第三代派生类可用使用它们。

      下面是比较图,其中隐式向上转换意味着无须进行显式类型转换,就可以将基类指针或引用指向派生类对象。

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/6.jpg

4.使用using重新定义访问权限

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/7.jpg

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/8.jpg

5.多重继承

      多重继承,MI,multiple interitance。 私有MI和保护MI可以表示has-a关系。这里主要讨论公有MI。

      虚基类技术:虚基类使得从多个类(它们的基类相同)派生出的对象只继承一个基类对象。通过在类声明中使用virtual,可以使Worker被用作Singer和Waiter的虚基类(virtual和public的次序无关紧要)。当类通过多条虚拟途径和非虚拟途径继承某个特定的基类时,该类将包含一个表示所有的虚拟途径的基类子对象和分别表示各条非虚拟途径的多个基类子对象。

         新的构造函数规则:

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/9.jpg

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/10.jpg

       MI常使用模块化方式,构造组件的技术来处理重定义方法的一些问题,下面是一个MI的例子:

       虚基类和支配:

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/11.jpg

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091021/12.jpg

6.类模板

     关键点:模板类的定义和实现要放在同一文件中。现在的编译器还不支持模板类的定义和实现分开。

http://hi.baidu.com/woiwojia/blog/item/d5ef994ee2499aced0c86a24.html

       一个类模板的例子:

      原型将赋值操作符函数的返回类型声明为Stack引用,而实际的模板函数定义将类型定义为Stack<Type>。前者是后者的缩写,但只能在类中使用。即可以在模板声明或模板函数定义内使用Stack,但在类的外面,即指定返回类型或使用作用域解析操作符时,必须使用完整的Stack<Type>.

      指定数组大小的数组模板,一种方法是在类中使用动态数组和构造函数参数来提供元素数目,另一种是使用模板参数来提供常规数组的大小。如下面这个例子:

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/1.jpg

      可以递归使用模板。例如对于上面的声明,这样使用它: ArrayTP< ArrayTP<int,5>, 10> twodee; 与之等价的常规数组声明如下: int twodee[10][5];

      可以将用于常规类的技术用于模板类。模板类可以用作基类,也可用作组件类,还可用作其他模板的类型参数。如:

      模板可以包含多个类型参数,如:

 

      还有一项特性是,可以为类型参数提供默认值:template <class T1,class T2=int> class Topo {...}.   虽然可以为类模板类型参数提供默认值,但不能为函数模板参数提供默认值。不过,可以为非类型参数提供默认值,这对于类模板和函数模板都是适用的。

7. 模板的具体化

      类模板与函数模板很相似,可以有隐式实例化,显式实例化和显式具体化,它们统称为具体化。

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/2.jpg

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/3.jpg

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/4.jpg

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/5.jpg

8. 成员模板

     模板可用作结构、类或模板类的成员。下面是一个简单的例子,该模板类将另一个模板类和模板函数作为其成员。

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/6.jpg

      有些编译器接受类外面的定义,上述代码和下面的代码等价:

      注意上面后面两个的嵌套句法。

9.将模板用作参数

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/1633918160989840000.jpg

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/2633918160990777500.jpg

10.模板类和友元

      模板类声明也可以有友元。模板的友元分3类:非模板友元;约束(bound)模板友元,即友元的类型取决于类被实例化时的类型;非约束(unbound)模板友元,即友元的所有具体化都是类的每一个具体化的友元。

1)模板类的非模板友元函数

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/3633918184763433750.jpg

2)模板类的约束模板友元函数

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/4633918185832965000.jpg

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/5633918186586715000.jpg

3)模板类的非约束模板友元函数

https://p-blog.csdn.net/images/p_blog_csdn_net/xuanya0214/EntryImages/20091022/6633918187675465000.jpg

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值