第十九天(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.




相关文章推荐

通向架构师的道路(第十九天)

  • 2012年11月19日 13:32
  • 1.97MB
  • 下载

IOS第十九天——登陆功能

刚在群里截图说了下学习的进展,果断被鄙视了,说我要是学了十天半个月的话,至少能写个登陆了,那么好吧,总打基础也不是个事儿不是?趁着今天时间比较充裕,来实现一个登陆的demo。 其实,还是在刚才那个基础...

通向架构师的道路(第十九天)使用maven构建Spring工程

通向架构师的道路(第十九天)使用maven构建Spring工程

Java进阶学习第十九天——dbutils与案例

元数据 数据库元数据 参数元数据 结果集元数据(重点) dbutils工具 DBUtils学习 Dbutlis详解 ResulsetHandler九个实现类 实现BeanHandler dbutils...

第十九天学习记录

django

黑马程序员--- 学习笔记(第十九天)

字符流缓冲区" BufferedReader,BufferedWriter 缓冲区的出现是为了提高流的操作效率而出现的,所以在创建缓冲区之前,必须要 先有流对象. BufferedWriter...

No_16_0316 Java基础学习第十九天

Map接口Map接口概述 将键映射到值的对象 一个映射不能包含重复的键 每个键最多只能映射到一个值 Map接口和Collection接口的不同 Map是双列的,Collection是单列的 Map的键...

黑马程序员-第十九天( IO(Input Output)流)

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------                     ...

Java学习第十九天

一、IO流概述及其分类 概念 IO流用来处理设备之间的数据传输 Java对数据的操作是通过IO流的方式 Java用于操作流的类都在IO包中 流按流向分为两种:输入...

第十九天 Http协议的学习

昨天servlet生命周期中,将用户的请求根据http协议打包发送给tomcat服务器,今天研究一下http协议是什么技术。 1.Http协议是什么? 它是超文本传输控制协议,定义了浏览器之间数据传输...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:第十九天(C++代码重用IV)
举报原因:
原因补充:

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