栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++模板编程(1)---类别模板Class Template

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++模板编程(1)---类别模板Class Template

1. QT中创建控制台程序工程,创建完添加类TemplateStack

2. 如下修改3个自动生成的文件

2.1 模板类的使用main.cpp

2.2 TemplateStack.h

2.3 TemplateStack.cpp

2.4 允许结果

 

3. 类模板说明

    类Class可以针对一或多个类型被参数化。比如用来管理各种不同类型元素的容器类container classes就是典型例子。用类别模板class template可以做出包含各种类型的容器类。上面的堆栈模板TemplateStack就是一个例子。 

      上面的定义和声明虽然在两个不同的文件中,实际使用时还是一个文件(因为main文件中include是cpp)。

    上面的TemplateStack 是以标准库的类模板class Template vector<> 为基础做出来的,这样我们就可以不用考虑内存管理、copy构造函数,赋值运算符等等,从而把注意力放在这个类模板class template的界面上。

3.1 类模板的声明

    声明类模板class templates和 声明函数模板 function templates类似:在声明语句之前加一条语句,以任意标识符声明类型参数type paramters, 常用大写T标识:

template 

 在函数模板中相同的规则再次适用:关键词class可以代替关键词typename:

template 与上面的template 等价

    在类模板class template内部,T就像其他任意类型一样,可用来声明成员变量(member variable)和成员函数(member functions)。本例子TemplateStack中T用来声明vector<>所容纳的元素类型、声明一个接受T const& 的push()函数、以及声明一个返回类型为 T的top()函数。

    这个class的类型为TemplateStack, T是一个模板参数template parmeter。现在以这个类声明变量或函数时,都应写成TemplateStack。例如,可以如下声明copy构造函数和assignment运算符:

template

class TemplateStack{

...

TemplateStack(TemplateStack const&);  //copy构造函数

TemplateStack& operator= (TemplateStack const&); //assignment运算符

...

};

然而如果只是需要class名称而不是class类型时,只需要Stack即可。构造函数和析构函数的声明就属于这种情况。

3.2 成员函数实现

为了定义类别模板class template的成员函数,我们必须指出它是个函数模板function template,且使用类模板class template的全称。因此TemplateStack的成员函数push()看起来像这样:

template

void TemplateStack:: push(T const& elem)

{

        elements.push_back(elem);

};

这里调用了vector的成员函数push_back(),把元素elem追加到elements尾端。

4. 类模板使用说明

    为了使用类模板class template 对象,必须明确指出其模板参数template argument。本例实现中

在main.cpp中声明了TemplateStack这样一个类型,表示在该类模板class template中T被替换为int。于是intStack称为这样一个对象object:内部使用“可容纳int数据为元素”的vector,并将被调用的任何成员函数都“以Int类型进行实例化”。stringStack同样的道理,与intStack相比只是模板参数类型从int换成了string。

运用typedef,可以方便地使用类模板class templates:

比如,typedef TemplateStack  IntStack;

IntStack istack[10];   // istack是一个“含有10 int stacks”的数组。

    模板参数Template arguments可以是任何参数,例如可以是指向float的指针,甚至是int stack:

    TemplateStack  floatPtrStack;    // stack of float pointers

    TemplateStack  > intStackStack;   // stack of stack

上面声明中 两个右括号之间必须插入一些空白符号,否则就使用了 》,导致语法错误。

5. 类模板Class Templates的特化(Specializations)

    可以针对某些特殊的template argument,对一个类型模板class template进行特化。类模板class template的特化与函数模板function template的重载类似,使你得以对某些特定类型进行程序代码优化,或修正某个特定类型的类模板class template实例中的错误行为。如果对一个class template进行特化,就必须特化其所有成员函数。

    要特化某个class template,必须以template<>开头声明此class,后面跟着希望特化的结果。特化类型(specialized type)将作为模板参数template argument,并在class名称之后直接写明:

template<>

class TemplateStack {

...

};

    对特化体(specialization)而言,每个成员函数都必须像常规的成员函数那样定义,每个T出现出都必须更换为特化类型(specialzied type):

下面是类型模板class template特化的完整的范例:

在原有类的声明中加入新文件(需要注意的是这里包含的templateStack.h是上面的h头文件与cpp文件总和)

#ifndef TEMPLATECLASSSPECIALIZE_H
#define TEMPLATECLASSSPECIALIZE_H
 
#include 
#include 
#include 
#include "templateStack.h"
 
template <>
class TemplateStack {
private:
    std::deque elements;
public:
    void push(std::string const&);
    void pop();
    std::string top() const;
    bool empty() const {
        return elements.empty();
    }
};
 
void TemplateStack::push(std::string const& elem)
{
    elements.push_back(elem);
}
 
void TemplateStack::pop()
{
    if(elements.empty()) {
        throw std::out_of_range("emplateStack::pop():empty stack");
    }
    elements.pop_back();
}
 
std::string TemplateStack::top() const
{
    if(elements.empty()){
        throw std::out_of_range("TemplateStack::top():empty stack");
 
    }
    return elements.back();
}
 
 
#endif // TEMPLATECLASSSPECIALIZE_H
 

6. 类模板的偏序特化

类模板Class templates可以被偏序特化,或称局部特化。这使得特定情形下使用特定代码,但程序员保留了选择模板参数template parameters的能力。例如下面的类模板class template:

template

class MyClass{

...

};

以下几种形式的偏序特化都是合理的:

  • 两个template paramter相同

template

class MyClass {

...

};

  • 第二个类型为int

template

class MyClass {

...

};

  • 两个template parameter均为指针类型

template

class MyClass {

...

};

以下例子示范分别使用哪种类模板class template:

MyClass mif; //使用MyClass

MyClass mff; //使用MyClass

MyClass mfi;  //使用MyClass

MyClass mp;    //使用MyClass

注意在实例化过程中,不能有歧义的情况发生,比如,

MyClass m; //错误,同时匹配MyClass和MyClass

MyClass mp;//错误,同时匹配MyClass和MyClass

7. 预设模板自变量Default Template Argument

    可以针对类模板定义其模板参数的默认值,这称为预设模板自变量default template arguments.

预设自变量参数的值可以引用前一步声明的模板参数。例如,在 Class TemplateStack<>中,可以把用来容纳元素的容器类型定义为第二个模板参数template parameter, 并使用std::vector<>作为其默认值。

具体工程实例如下,同样创建控制台程序。

//defaulttemplatearg.h

#ifndef DEFAULTTEMPLATEARG_H
#define DEFAULTTEMPLATEARG_H
 
#include 
#include 
 
template  >
class TemplateStack {
private:
    CONT elements;
public:
    void push(T const&);
    void pop();
 
    T top() const;
    bool empty() const {
        return elements.empty();
    }
};
 
template 
void TemplateStack::push(T const& elem)
{
    elements.push_back(elem);
}
 
template 
void TemplateStack::pop()
{
    if(elements.empty()) {
        throw std::out_of_range("pop() empty stack");
    }
    elements.pop_back();
}
 
template 
T TemplateStack::top() const
{
    if(elements.empty()) {
        throw std::out_of_range("top() empty stack");
    }
    return elements.back();
}
 
#endif // DEFAULTTEMPLATEARG_H

//main.cpp

#include 
#include 
#include 
#include 
#include "defaulttemplatearg.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
 
    try {
        TemplateStack intStack;
        TemplateStack > dblStack;
 
        intStack.push(8);
        std::cout << intStack.top() << std::endl;
        intStack.pop();
 
        dblStack.push(66.66);
        std::cout << dblStack.top() << std::endl;
        dblStack.pop();
        dblStack.pop();
    } catch (std::exception const& ex) {
        std::cerr << "Exception: " << ex.what() << std::endl;
        return  EXIT_FAILURE;
 
    }
 
    return a.exec();
}

8. 总结

  • 所谓类模板class template是“包含一个或多个尚未确定类型”的class。必须将具体类型当作模板参数template argument传入后才能使用类模板 class template。于是该类模板 class template 就以传入的指定类型,由编译器实例化并编译。
  • 在类模板class template中,只有实际被调用的成员函数,才会被实例化。
  • 可以针对特定类型,对模板类class template进行特化(sepcialize)。
  • 可以针对某些特定类型,对模板类class template进行偏序特化(partially specialize).
  • 可以为模板参数template parameters定义默认值(default template argument),该预设自变量值可以引用前一步定义的模板参数template parameters。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/971315.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号