泛型编程和模板,泛型编程模板

 

泛型编程和模板,泛型编程模板

泛型编程就是以独立于任何特定类型的方式编写代码,而模板是泛型编程的基础。

1)定义函数模板(function template)

函数模板是一个独立于类型的函数,可以产生函数的特定类型版本。

模板定义以关键字template开始,后接尖括号括住的模板形参表。

模板形参可以是表示类型的类型形参(type
parameter),也可以是表示常量表达式的非类型形参(nontype
parameter)。下面程序中的T是类型形参。我会在另外的文章里分析类型形参和非类型形参。

// implement strcmp-like generic compare function
template <typename T>
int compare(const T &v1, const T &v2)
{
    if (v1 < v2) return -1;
    if (v2 < v1) return 1;
    return 0;
}

使用函数模板时,编译器会将模板实参绑定到模板形参。编译器将确定用什么类型代替每个类型形参,用什么值代替每个非类型形参,然后产生并编译(称为实例化)该版本的函数。

下面的例子中,编译器用int代替T创建第一个版本,用string代替T创建第二个版本。

// compiler instantiates int compare(const int&, const int&)
cout << compare(1, 0) << endl;
// compiler instantiates int compare(const string&, const string&)
string s1 = “hi”, s2 = “world”;
cout << compare(s1, s2) << endl;

函数模板也可以声明为inline。

// inline specifier follows template parameter list
template <typename T> inline T min(const T&, const T&); 

(2)定义类模板(class template)

威尼斯网址开户网站 ,在定义的类模板中,使用模板形参作为类型或值的占位符,在使用类时再提供具体的类型或值。

template <typename Type> 
class Queue
{
public:
    Queue();
    Type & front();
    const Type & front() const;
    void push(const Type &);
    void pop();
    bool empty() const;
private:
    // …
};

与调用函数模板不同,使用类模板时,必须为模板形参显示指定实参。

Queue<int> qi; // Queue that holds ints
Queue<string> qs; // Queue that holds strings

(3)模板类型形参

类型形参由关键字class或typename后接说明符构成。在函数模板形参表中,二者含义相同。typename其实比class更直观,更清楚的指明后面的名字是一个类型名(包括内置类型),而class很容易让人联想到类声明或类定义。

此外,在使用嵌套依赖类型(nested depended
name)时,必须用到typename关键字。

在类的内部可以定义类型成员。如果要在函数模板内部使用这样的类型,必须显示告诉编译器这个名字是一个类型,否则编译器无法得知它是一个类型还是一个值。默认情况下,编译器假定这样的名字指定(静态)数据成员,而不是类型。所以下面这段程序,如果去掉typename关键字,将会出现编译错误。

template <typename Parm, typename U>
Parm fcn(Parm *array, U value)
{
    typename Parm::size_type * p;
}

(4)非类型模板形参

模板形参也可以是非类型形参,在使用时非类型形参由常量表达式代替。

// initialize elements of an array to zero
template <typename T, size_t N>
void array_init(T (&parm)[N])
{
    for (size_t i = 0; i != N; ++i)
        parm[i] = 0;
}
…
int x[42];
double y[10];
array_init(x); // instantiates array_init(int (&)[42])
array_init(y); // instantiates array_init(double (&)[10])

(5)编写泛型程序

模板代码需要对使用的类型做一些假设,比如上面的compare()要求类型T重载了“<”操作符。所以函数模板内部完成的操作就限制了可用于实例化该函数的类型。

编写模板代码时,对实参类型的要求应尽可能少。比如compare()函数仅使用了“<”操作符,而没有使用“>”操作符。

泛型编程就是以独立于任何特定类型的方式编写代码,而模板是泛型编程的基础。
1 )定义函数模板(fu…

泛型类与非泛型类之间的继承
1,泛型类与非泛型类之间的继承

泛型的概念
1,什么是泛型
1,泛型是JDK5.0新添加的特性。
2,泛型就是将类型参数化。
3,提高类型的安全并能简化类型转换的过程。在泛型处理过程中,所有的类型转换
都是自动和隐式的。
泛型将类型的错误提前到了编译期
2,没有泛型的情况
数据类型转换比较复杂。
String i2=(String)g1.getObj();
String s2=(String)g2.getObj();
在转换中会产生不安全的因素。

泛型类之间的继承
1,泛型类之间的继承
GenChild<T,V,K> extends GenParent<T>
定义泛型子类,声明中必须包含其父类的类型参数。即便在子类中不适用,仍然
要在参数列表中指定它。

   Veneers的概念相当简单,一个Veneer其实就是一个类模板,它拥有以下特征:

父类是泛型类,子类不是泛型类。如果子类继承了带泛型的父类,则
    子类必须得是泛型类,并且包含父类的泛型。
    public class Child<T> extends GenParent<T>

父类不是泛型类,子类是泛型类,正常写就可以,没有强制性的要求。
    public class GenChild<T> extends Parent

         1)它从自己的主模板参数派生而来(常以public方式)

         2)它不定义任何虚方法

         3)它不定义任何非静态成员变量,也不定义虚拟析构方法

        
4)在2)和3)的基础上更进一步,相比于模板参数类,它并不会增加复合类的内存访问频率。

        
Veneers常常更改了模板参数类的行为或类型。更改行为采用的方法是使用次模板参数提供的额外功能来补充现有功能。

        
考虑一种情况:向一个非常严密的层次结构中注入新的功能,ATL中的CWindow是一个很好的例子。CWindow没有可以获取对话栏文本长度的成员函数,我们可以使用Win32的API函数GetWindowTextLength()以及CWindow的成员函数GetDlgItem()来创建一个Veneer类parent_window_veneer,其代码如下所示:

template<typename T> 

 

classparent_window_veneer : public T 

 

 

public: 

 

    typedef T ParentClass; 

 

    typedef parent_window_veneer<T> Class; 

 

//construction 

 

public: 

 

    …… 

 

//operations 

 

public: 

 

    int GetDlgItemTextLength(UINT id)  

 

    { 

 

       return ::GetWindowTextLength(GetDlgItem(id)); 

 

    } 

 

}; 

        
任何可能用到CWindow类的地方都可以用parent_window_veneer<CWindow>替换,这样一来GetDlgItemTextLength()方法在该类或该类的派生类的实例中就可以使用了。当然不采用模板化继承也可以实现这一功能,但是如果之后你又想将这个函数添加到另外一个ATL窗口类(如CContainedWindow)中,你就不得不再写一个派生类,以此类推。Veneer很容易被各种类型的窗口类使用,只要它们含有兼容的GetDlgItem()成员函数即可,剩下唯一要做的事就是修改一下类型定义(typedef)。

        
Veneers也可以提供析构方法,不过需要注意的是:如果模板参数不是一个多态可继承的类型(比如它不包含一个虚拟析构方法),就不要将它多态地使用。

        
最后,因为Veneers与它们的模板参数类型大小相同,因此在需要数组的情况下可以用Veneers替换其模板参数类型。

         Veneers的优势包括:

在不重复编写代码的前提下向继承层次结构成功注入了新的功能代码

它们可被用来向已存在的类中增加资源自动清理的功能,常使用RAII手法。(STLSoft库中的容器Veneers为C++标准库中的容器类提供了这样的功能)

大小的限制意味着参数化的Veneer类型可以在数组形式中使用,而不会碰到异构数组的问题

        
STLSoft库中有一些Veneers类的实际例子,包括pod_veneer,conversion_veneer,sequence_container_veneer以及associative_container_veneer。你可以查看这些类的说明文档以加深对Veneers概念的理解。

来源:

翻译:[email protected]

关键字:模板化继承、泛型继承、templatedinheritance、generic
inheritance、Veneers

1)它从自己的主模板参数派生而来(常以public方式) 2)它不定义任何…

相关文章