C++ 将与参数无关的代码抽离出模板(templates)

20180330 C++ 将与参数无关的代码抽离出模板(templates)



模板使得你不再需要写20个类似的类而每一个带有15个成员函数,你只需要写一个类模板,留给编译器去具现化那20个你需要的相关类和300个函数(类模板的成员函数只有在被使用时才被暗中具现化,所以只有在这300个函数的每一个都被使用,你才会获得者300个函数)。
函数模板也是类似的。你只需要写一个函数模板,就可以替换很多函数,然后让编译器做剩余的事。


有时候使用模板可能会导致代码膨胀(code bloat):其二进制码可能带着重复(或几乎重复)的代码或数据,或两者都带有。其可能导致源码看起来整整齐齐,,而目标码可能导致冗余,那如何避免这个问题呢?
你要会进行共性与变性分析(commonality and variability analysis)。
即当你在编写某个类时,当你发现其中某些部分,和另一个类的某些部分相同,你不会重复相同的部分。。取而代之的是,你会把共同的部分搬移到新的类中,然后使用继承或复用,令原先的类取用这共同特性。而原先类的互异部分仍然留在原位置不动。






编写模板时,重复是隐晦的,:毕竟只存在一份模板源码,所以你必须训练自己去感受当模板被具现化多次时,可能发生的重复。


eg:


//需要为固定尺寸的正方形矩阵编写一个模板,该矩阵的性质之一就是支持逆矩阵运算(//matrix inversion)。


template<typename T,std::size_t n>
/*
模板支持n*n矩阵,元素是类型为T的目标(objects)
*/


class SquareMatrix{
public:
  ...
  void invert();//求逆矩阵
}




这个模板接受一个类型参数T,除此之外还接受一个类型为size_t的参数,那是个非类型参数。
现在考虑如下代码:
SquareMatrix<double,5> sm1;
...


sm1.invert();//调用SquareMatrix<double,5>::invert()




SquareMatrix<double,10> sm2;
...


sm2.invert();//调用SquareMatrix<double,5>::invert()




这会具现化两份invert。这些函数并非完全相同,因为其中一个操作的是5*5矩阵,另一个操作的是10*10矩阵,但除了常量5和10,两个函数的其他部分完全相同。这个是模板引出代码膨胀的一个典型例子。








为了不重复代码,需要为它们建立一个带数值参数的函数,然后以5和10来调用这个带参数的函数,下面就是对SquareMatrix的第一次修改:


template<typename T>
class SquareMatrixBase
{
protected:
  ...
  void invert(std::size_t matrixSize);//以给定的尺寸求逆矩阵
  ...
};


template<typename T , std::size_t n>
class SquareMatrix: private SquareMatrixBase<T>
{
private:
using SquareMatrixBase<T>::invert;//避免遮掩基类版本里的invert
public:
 ...
  void  invert() {this->invert(n);}
  /*制造一个invert调用,调用基类里的invert。*/


};


就像以上代码显示的那样,带参数的invert位于基类的SquareMatrixBase里,和SquareMatrix一样,SquareMatrixBase也是一个模板,不同的是它只对“矩阵元素对象的类型”参数化,不对矩阵的尺寸参数化。因此对于某给定的元素对象类型,所有矩阵共享同一个(也是唯一一个)SquareMatrixBase类,它们也将因此共享这唯一一个类内的invert。


SquareMatrixBase::invert只是企图成为“避免派生类代码重复”的一种方法,所以它以protected替换public。调用它而造成的额外成本应该是0。因为派生类的inverts调用基类版本时用的是inline调用(这里的inline是隐晦的)。这些函数使用“this->”记号,因为若不这样做,模板化基类(template base classes,如SquareMatrixBase<T>)内的函数名称会被派生类覆盖。另外SquareMatrix和SquareMatrixBase之间的关系是private。这反应的事实是:这里的基类只是为了帮助派生类实现,不是为了表现SquareMatrix和SquareMatrixBase之间是is-a的关系。




/************************全TM没看懂************************************/










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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值