第十九天(C++代码重用IV)

原创 2012年03月23日 09:13:00

        昨晚写完已断网,故而今早上传。另,可能是这章内容太多,可能是我太过啰嗦,这章居然被我分了五部分。今天或者明天,还会有part V


2012-3-22(Reusing Code in C++part IV)

13. Class Templates

Inheritance and containment aren't always the solution when you want to reuse code. Instead, using class templates are more commonly. Like function templates, templates instructions to the C++ compiler about how to generate class definitions. Unlike function templates, class templates provide parameterized types---that is, the capable of passing type name as an argument to a recipe for building a class.

I. Syntax

A typical class model would like this:         

class exam
{
private:
  	int member;
public:
   	int function1();
	exam function2();
};
Then, if we want to declare a class template,modify it as follows:
template <class Type>		//or <typename Type>
class exam
{
private:
  	Type member;
public:
   	Type function1();
	exam function2();
}

Also,you need to make a little change when defining member functions:

template <class Type>
Type exam<Type>::function1()  {/*function body*/}

template <class Type>
exam<Type> exam<Type>::function2() {/*function body*/}
We need to change the class qualifier from exam:: to exam<Type>::. But we can use exam:: or exam instead of exam<Type>:: or exam<Type> inside the template declaration and template function definitions.

II. Caution

Again, class templates are not class and member function definitions. Rather, they tell the compiler to how to generate a specific class. A particular actualization of a template is called an instantiation or a specialization.Because, the templates aren't functions, placing the template member functions in a separate implementation file won't work, unless you use a compiler that has implemented the new export keyword.

But most of compilers,including Microsoft Visual Studio 2010 Express that I am using are not yet support this keyword  (warning in VS2010):

        'export' keyword is not yet supported,but reserved for future use

Looking for the reason in the Internet: too complex to implement.

It's strange that when I try to separate declaration and implementation, my compiler reports no problem.I don't know why. For compatibility, we are supposed to place all the template information in a herder file.

 

14. Design a Simple Array Template

Templates are frequently used for container classes because the idea of type parameters matches well with the need to apply a common storage plan to a variety of types. A typical array template has the following functions (a portion):

  •   size ();                 //return the number of elements
  •   operator []();        //set and get the value of element

We need to specify an array size when creating an array. Two techniques to reach this goal: one is use a dynamic array within the class and a constructor argument to provide the number of elements. Another approach is to use a template argument to provide the size for a regular an ordinary array.

I. Dynamic Array 

#ifndef _DARRAY_
#define _DARRAY_

template <typename T>
class DArray
{
private:
    int array_size;
    T* elems;
public:
    DArray (int size = 10);      //contructor
    DArray (const DArray& da);  //copy contructor
    ~DArray(){delete[] elems;}    //destructor

    int size() {return array_size;}
    const T& operator [](int i) const;   //prepare for const objects
    T& operator [](int i);          	      //get & set certain element
    DArray& operator =(const DArray& da);    //assignment operator
};

template <typename T>
DArray<T>::DArray(int size = 10): array_size(size)
{
    elems = new T[size];
}

template <typename T>
DArray<T>::DArray(const DArray& da)
{
    array_size = da.array_size;
    elems = new T[array_size];

    for(int i = 0; i< array_size; i++) elems[i] = da.elems[i];
}

template <typename T>
const T& DArray<T>::operator [](int i) const
{
    return elems[i];
}

template <typename T>
T& DArray<T>::operator [](int i)
{
    return elems[i];
}

template <typename T>
DArray<T>& DArray<T>::operator =(const DArray& da)
{
    if(this == &da) return *this;

    delete[] elems;
    array_size = da.array_size;
    elems = new T[array_size];
    for(int i = 0; i< array_size; i++)
        elems[i] = da.elems[i];
    return *this;
}
#endif
Using dynamic array internally, so the class needs a destructor, copy constructor and an assignment operator.

II. Non-Type Arguments

#ifndef _NARRAY_
#define _NARRAY_

template <typename T, int n>
class NArray
{
private:
    T elems[n];
public:
NArray() {}         //default constructor
//create an object that all elements are e
explicit NArray(const T& e); 

int size() const { return n; };
const T& operator [](int i) const;
T& operator [](int i);
};

template <typename T, int n>
NArray<T,n>::NArray(const T& e)
{
    for(int i = 0; i< n; i++) elems[i] = e;
}

template <typename T, int n>
const T& NArray<T,n>::operator[](int i)const
{
    return elems[i];
}

template <typename T, int n>
T& NArray<T,n>::operator[](int i)
{
    return elems[i];
}
#endif
template heading template <typename T, int n>, whose second kind of parameter specifies a particular type instead of acing as a generic for a type, is called a non-type(or expression) argument.

Non-type arguments have some restrictions. Anon-type can be an integral type, an enumeration type, a reference or a pointer. Also, the templates code can't modify the value of the argument or take its address. In other word, expression like n++ or &n  would not be allowed inside the class templates. And when instantiate a template, the value used for the expression argument should be a constant expression.

III. Testing

Two techniques have the same name of interface, so I can use a similar test program.

#include <iostream>
//#include "NArray.h"
#include "DArray.h"

using namespace std;

int main()
{
   //NArray<double,7> da(5.0);
   DArray<double> da(7);
   cout << da.size() << endl;

   for(int i = 0; i< 6; i++) da[i] = double(i * 2);
   //const NArray<double,7> nda = da;
   const DArray<double> nda = da;
   
   for(int i = 0; i< nda.size(); i++) 
      cout << nda[i] << " ";
   cout << endl;   
   for(int i = 0; i< da.size(); i++) 
       cout << da[i] << " ";
}

The comment portion is prepare for non-type argument.

VI. Comparison

① Argument approach has less execution time. Constructor approach uses heap memory managed by new and delete, while expression argument uses the memory stack maintained for automatic variables.

② Argument approach costs more resource. For example

                           NArray<int,7> one;

                           NArray<int,8> two;

generate two separate class declarations. But

                                  DArray<int> one(7);

                              DArray<int> two(8);

generate just one separate declaration.

③ Constructor approach is more versatile. Because its array size is stored as a class member. So that, for example, we can assignment from an array of one size to an array of another size or to define a function to resize the array.




C++关于代码重用的那些事

C++的另一个目标是促进代码重用。公有继承是实现这种目标的机制之一,但并不是唯一的机制。还可以使用这样的类成员:本身是另一个类的对象,这种方法称为包含、组合或层次化。另一种方法是使用私有继承或保护继承...
  • Mr_Avin
  • Mr_Avin
  • 2017年02月17日 15:27
  • 951

C/C++第十九天

构造函数: 函数名跟类名一模一样 即是一个普通的函数又是一个不普通的函数 不普通:名称跟类一样 系统会自己调用构造函数 可以使用构造函数对类里面无法访问的数据进行初始化与修改 构析...
  • qq_35647829
  • qq_35647829
  • 2016年08月17日 19:11
  • 83

第十六天(C++代码重用)

看下日期,一共3个多月没写。再次“执笔”亦需下不少的决心。今天的不长,一来表明自己不会太监。二来亦需重回写程序的状态。老规矩,还是会用英文写的。 2012-3-10(Reusing Code...
  • fkanf
  • fkanf
  • 2012年03月10日 21:45
  • 269

C++第十九天 面向对象编程

#include #include //继承与组合: // 继承:定义一个类作为另一个类的公用派生类时,派生类应反映与基类“是一种 Is a” 的关系。 // 组合:组合关系是“有一个Has a”的...
  • liangguojunainia
  • liangguojunainia
  • 2014年08月09日 10:08
  • 234

代码重用和接口重用

在面试中,面向对象语言中经常会提到代码重用和接口重用的概念,有些同学会很疑惑,其实仔细翻阅下书本就不难发现,代码重用就是继承父类的方法,达到方法(代码)重用的目的,而接口重用就是在多态中能够通过父类指...
  • zsczsc1011
  • zsczsc1011
  • 2015年08月27日 17:24
  • 1281

c/c++第十九天

虚函数
  • yeruida
  • yeruida
  • 2016年08月22日 20:46
  • 145

C++中代码的重用

类模板与模板类的概念 (1) 什么是类模板 一个类模板(也称为类属类或类生成类)允许用户为类定义一种模式,使得类中的某些数据成员、默认成员函数的参数、某些成员函数的返回值,能够取任意类型(包括系统...
  • qq_35080659
  • qq_35080659
  • 2017年02月26日 13:25
  • 76

c++的代码重用

一、公有继承 不是实现代码重用的唯一途径,还有很多其他途径---包含,组合或者层次化,使用私有或保护继承,多重继承 二、类 valarray 头文件 valarray。这个类用于处理数值,...
  • u012730315
  • u012730315
  • 2015年04月13日 20:05
  • 762

第十九天

2017/8/21 14:05b:开始 2017/8/21 17:07s:收集了python和工作相关资料,总结:还是以兴趣为驱动,目前的兴趣仍是爬虫,以找到python相关工作为大目标,在...
  • python_fish
  • python_fish
  • 2017年08月21日 22:05
  • 49

第十七天(C++代码重用II)

前几天装了个win7 x64(D版),无他,一为图个新鲜,二为告别硬盘的游戏(虽然装系统不影响非系统盘),寓为新的开始。也正因为这个x64,导致我今天下午开的网银死活不能初始化U盾……可能是64位的原...
  • fkanf
  • fkanf
  • 2012年03月16日 23:46
  • 206
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:第十九天(C++代码重用IV)
举报原因:
原因补充:

(最多只允许输入30个字)