Effective C++学习_条款44:将与参数无关的代码抽离

  当你编写某个函数,而你明白其中某些部分的实现码和另一个函数的实现码实质相同,你会很单纯地重复这些码吗?当然不。你会抽出两个函数的共同部分,把他们放进第三个函数,然后令原先两个函数调用这个新函数。同样道理,在编写类的时候你也会以相同的方式来避免重复。

  举个 例子:假设 你想为一个尺寸固定的正方矩阵编写一个template。该矩阵的性质之一是支持逆矩阵运算。

template<typename T, size_t n>
class SquareMatrix
{
public:
    void invert();  // 求逆矩阵
};

  我们来定义两个正方矩阵对象:

SquareMatrix<double, 5> sm1;

sm1.invert();
SquareMatrix<double, 5> sm2;

sm2.invert();

  这会具现化两份invert。这些函数并非完全不同,因为其中一个操作的是5*5矩阵而另一个操作的是10*10矩阵,但除了常量5和10,两个函数的其他部分完全相同。这是template引出代码膨胀的一个典型例子。
  
  我们考虑做如下修改:

template<typename T>
class SquareMatrixBase
{
public:
    SquareMatrixBase(size_t n, T* ptr) : size(n), ptr(pdata);
    void invert(std::size_t matrixsize);

private:
    size_t size;
    T* pdata;
};

template<typename T, size_t n>
class SquareMatrix : private SquareMatrixBase
{
public:

    SquareMatrix() : SquareMatrixBase<T>(n, data) {}
    void invert(std::matrixsize n)
    {
        SquareMatrixBase::invert(n); //利用了条款43的性质
    }

private:
    T data[n*n];
};

  正如你所看到,带参数的invert位于base class SquareMatrixBase中。和SquareMatrix一样,SquareMatrixBase也是个template,不同的是它只对“矩阵元素对象的类型”参数化,不对矩阵的尺寸参数化。因此,对于某给定值元素对象类型,所有矩阵共享同一个SquareMatruxBase class。它们也将因此共享这唯一一个class内的invert。另外,为了使SquareMatrixBase可以访问数据,从而求逆运算,这里声明了它的指针成员,这个指针将会在构造时指向子类的数据存储空间。

  目前只是说将与类型无关的代码进行抽离(造一个父类,把算法相同的部分提取出来,放到父类),对于不同类型,其实也可以通过void* 来实。比如STL,要想令我们使用list< int* >,list< const int* >生成的代码冗余度保持很低,这就需要在相应的函数里面,将之链到父类的一个公共实现版本里面,这个版本的形参是void*。

  总结
  1. template生成多个classes和多个函数 ,所以任何template代码都不应该与某个造成膨胀的template参数产生相依关系。
  2. 因非类型模板参数而造成的代码膨胀,往往可以消除,做法是以函数参数或class成员变量替换template参数。
  3. 因参数类型而造成的代码膨胀,往往可降低,做法是让带有完全相同二进制表述的具现类型共享实现码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值