泛型编程深入探索(一) 模版高级特性小结

一些基本的模版特性:

非类参数模版

模版所声明的参数可以不是类参数,可以声明的非类参数包括整数(double,float不可以),enum,对象引用或指针。

通过模版嵌套实现类或非类参数载类方法参数上的重载(调用时实现,不在定义时实现)

友元函数模版:

直接举例:

template <typename T>

friend ostream& operator<< <T>(ostream& os, const T& t){};

内联模版函数:

模版定义必须在头文件中,所以所定义的函数并不直接是内联的,需要确定声明该函数是内联的。

inline void func(){};    //在模版类定义中

inline void A<T>:: func{};  //在模版类定义外

高级模版特性:

模版嵌套

当在某个模版类的参数调用时,无论是类参数还是非类参数,需要另一个模版参数,使用模版嵌套。

值得注意的时,模版嵌套不能handle当参数模版的参数和原模版的参数为同一个类的情况,因此,必须要保留无模版嵌套的原始情况完成模版方法函数的重载。

另外,模版嵌套的优先级是:

对于未使用参数模版,即参数全部使用原模版参数的方法,单独定义,单独调用。

一旦参数中使用了嵌套模版,则一定触发某个嵌套模版方法,触发的顺序是,

触发仅改变所有模版化参数的方法重载,如果没有,则逐级触发包括了更多未改变参数的嵌套模版。

测试代码如下:

template <typename T,int SCORE>
class vec{
    T a;
    int sc;
public:
    T getA()const {return a;}
    int getScore() const {return sc;}
    vec(T t):a(t),sc(SCORE){};
    //参数中未使用模版嵌套的拷贝构造,必须有
    vec(const vec<T,SCORE>& vv):a(vv.a),sc(vv.sc){cout<<"copyT is called"<<endl;};
    //参数score模版化的拷贝构造
    template <int OTHER>
    vec(const vec<T,OTHER>& vv):a(vv.getA()),sc(vv.getScore()){cout<<"copyOther is called"<<endl;};
    //参数t和score均发生模版化的拷贝构造
    template <typename E,int OTHER>
    vec(const vec<E,OTHER>& vv):a(vv.getA()),sc(vv.getScore()){cout<<"copy is called"<<endl;};
    virtual ~vec();
};

模版偏特化与函数模版重载偏特化

模版通过重写一个具体类实现模版的偏特化(即某个具体类不按照模版实现),函数没有偏特化的功能,因此,通过重载实现。

优先级均为:

确定类,确定指针/引用/对象的模版类,任意模版类的顺序调用。

特殊的,模版全特化

所有模版参数都被特化,此时,函数可以特化,且特化类的函数重写不需要加上模版声明template<>

偏特化测试代码

#include <iostream>

template <typename T>
class pointertemp{
public:
    T name;
    pointertemp():name(T()){std::cout<<"original ctr callled"<<std::endl;};
};

template <typename T>
class pointertemp<T*>{
public:
    T* name;
    pointertemp():name(nullptr){std::cout<<"T* ctr callled"<<std::endl;};
};

template <>
class pointertemp<char*>{
public:
    char* name;
    pointertemp():name(nullptr){std::cout<<"char* ctr callled"<<std::endl;};
};

template <typename K>
void showK(K name){
    std::cout<<"K func called";
}

template <typename K>
void showK(K* name){
    std::cout<<"K* func called";
}

void showK(char* name){
    std::cout<<"char* func called";
}

值得注意的是,当T为指针或者引用时,在找不到匹配的具体类的特化实现时,编译器会取找有没有指针特化或者引用特化,这些都优先于未特化模版。

且在指针特化和引用特化时,用<A*>实例化,但模版参数其实是A,也就是说<A*>实例化实际上是将A赋予T,然后使用指针特化模版。

本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/project/

模版继承:

模版类可以实现继承和多态,一般的,子类继承父类的同参数实例类,如果要继承任意类参数的实例类,只需要在模版中多声明一个父类类参数即可。

模版参数模版

模版嵌套用来模版化类模版的方法参数,特化用来重载模版的某一个特例类型的实现或者重载一个类集合;

常用于声明一个模版,他的参数是一个模版类实例

基本语法如下,当使用了模版参数模版后,模版的模版参数在模版的定义内实例化,不需要外部实现。

用来实例化模版参数的类可以是任意确定类或者模版声明的其他类参数。

模版参数模版的意义在于,在模版定义时即确定了其参数模版的参数,不需要在调用时由被调用者确定,应区别下面三种模版的声明:

//通过模版参数模版,使得模版的参数模版可以使用任意类,但该类在原模版的定义中实例化确定。
template <typename T, template<typename E> class container>
class temptemp{
    //模版参数在这里实例化
};
//调用: temptemp<int ,vector>

//模版参数模版使用确定类,该类需要用户自己声明,但只能声明确定类,一旦声明其他类,编译器会报错
template <typename T, typename container<T>>
class A;
//调用: temptemp<int ,vector<int>>
//调用: temptemp<int ,vector<double>>是编译错误的

template <typename T, typename container<E>>
class A;
//调用: temptemp<int ,vector<int>>是编译错误的
//调用: temptemp<int ,vector<double>>

//上述两个可实现模版重载

基本用法如下:

template <typename T, template<typename E, typename allocator=allocator<E>> class container>
class temptemp{
public:
    container<T> vt;
    container<int> vint;
    void show(){
        vt.resize(10);
        vint.resize(10);
        vt.at(0)=3;
        vint.at(0)=12;
        std::cout<<vt[0]<<"\t"<<vint[0]<<endl;
    }
};

类型推导模版:

区别auto和decltype

二者均返回一个类型名,其返回值用法与int或者自定义的A没有区别。

二者的区别在于:

decltype(expr)在运行这句时动态决定一个类型,内部要一个确定的表达式(不能含有模版)。

auto 是占位符,表示这里所需要确定的类型在之后变量初始化或函数声明后确定。

变量直接通过初始化确定,函数返回值通过trailing确定,即在函数声明后加上-> decltype(expr)(此时,可以由模版对象,因为模版编译到此刻时已经确定类型了)或确定的变量与表达式。

auto参不允许出现在函数原型中!

考察这样的一个类型推导型的模版:

template <typename T,typename E>
auto func (const T& a,const E& b) ->decltype(a*b){
    auto s=decltype(a*b)();
    return s;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索指针
, 友元
, 参数
, 泛型编程
, 整数
, 类模版
, 特性
, 高级特性
, 小结
, 深入探索c
, 模版
模版操作类
深入理解java泛型详解、java泛型深入理解、个性特征探索小结、深入探索c 对象模型、职业能力探索小结,以便于您获取更多的相关知识。

时间: 2024-09-19 09:16:33

泛型编程深入探索(一) 模版高级特性小结的相关文章

深入理解Java虚拟机:JVM高级特性与最佳实践

目 录 [ - ] <深入理解Java虚拟机:JVM高级特性与最佳实践>前言 <深入理解Java虚拟机:JVM高级特性与最佳实践>内容特色 <深入理解Java虚拟机:JVM高级特性与最佳实践>目录 第1章 走近Java 1.1 概述 1.2 Java技术体系 1.3 Java发展史 1.4 展望Java技术的未来 1.4.1 模块化 1.4.2 混合语言 1.4.3 多核并行 1.4.4 进一步丰富语法 1.4.5 64位虚拟机 1.5 实战:自己编译JDK 1.5.1

PHP高级特性讨论之邮件相关

高级 邮件发送和收取是目前网上交流最为重要的途径之一,我们当然很希望自己的PHP程序也能够实现某些商业网站注册程序中采用的方法,即通过邮件方式进行密码(或激活码)发送和资料确认.另一方面,这种方式也是一种反馈用户信息的有效途径.当然,要实现这些功能是离不开邮件服务器的,目前比较流行的Mail服务器(更准确的说是邮件传输代理MTA)有:sendmail.qmail.postfix.至于如何配置其中的pop.smtp.imap等服务已经超出这篇文章的范围,读者可以参考其他这方面文章.那么好了,我们究

JavaFX Script高级特性

JavaFX 是 Sun 推出的一套基于 Java 技术的产品家族. JavaFX Script 可以用来高效的创建富媒体和交互性很强的应用. JavaFX 是 Adobe Flex 和 Microsoft Silverlight 的有力竞争者.本文通过具体的实例介绍了 JavaFX Script 语言本身的一些高级特性并讨论了 JavaFX Script 中的一些高级话题,包括创建复杂的用户界面.实现动画效果.JavaFX Script 应用的部署和在一个独立的 Java 应用程序中嵌入 Ja

《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一导读

前 言 致读者 本书是按照Java SE 8完全更新后的<Java核心技术 卷Ⅱ 高级特性(原书第10版)>.卷Ⅰ主要介绍了Java语言的一些关键特性:而本卷主要介绍编程人员进行专业软件开发时需要了解的高级主题.因此,与本书卷Ⅰ和之前的版本一样,我们仍将本书定位于用Java技术进行实际项目开发的编程人员. 编写任何一本书籍都难免会有一些错误或不准确的地方.我们非常乐意听到读者的意见.当然,我们更希望对本书问题的报告只听到一次.为此,我们创建了一个FAQ.bug修正以及应急方案的网站http:/

《iOS组件与框架——iOS SDK高级特性剖析》——第2章,第2.4节地图注释和覆盖层

2.4 地图注释和覆盖层 iOS组件与框架--iOS SDK高级特性剖析 地图视图(MKMapView)是一种可滚动的视图,行为独特:以标准方式在其中添加子视图时,子视图不会随地图视图滚动,而是静止的,其相对于地图视图框架的位置始终不变.对悬停按钮或标签来说,这种特点也许不错,但在地图上标出点和细节至关重要.要标出地图视图中感兴趣的点或区域,可使用地图注释和覆盖层.地图滚动或缩放时,注释和覆盖层在地图上的位置保持不变.地图注释是使用地图上的单个坐标点定义的,而地图覆盖层可以是线段.多边形或复杂形

《Java数字图像处理:编程技巧与应用实践》——1.4 Swing Java 2D的其他高级特性介绍

1.4 Swing Java 2D的其他高级特性介绍 1 . Stroke接口 Stroke是Graphics2D的API接口,用来实现图形的描边修饰,在Java 2D中只有一个完成Stroke接口的类BasicStroke,如果有需要,可以自己完成Stroke接口,实现自定义的Stroke类.如何使用Stroke的实现类?方法如下: 1)调用Graphics2D 的setStroke()方法,传入一个实例化的Stroke对象. 2)调用draw()方法,传入要绘制的几何形状. BasicStr

《iOS组件与框架——iOS SDK高级特性剖析》——第6章,第6.2节打造播放引擎

6.2 打造播放引擎 iOS组件与框架--iOS SDK高级特性剖析 如果对播放控制没有深刻认识,获取音频数据将毫无意义.要在应用中播放音乐,需要创建一个MPMusicPlayerController实例.在头文件ICFViewController.h中,声明了一个名为player的MPMusicPlayerController变量,在整个示例应用中,都将使用它来控制播放以及获取当前播放的曲目的信息. 在方法viewDidLoad中,初始化了MPMusicPlayerController变量pl

《iOS组件与框架——iOS SDK高级特性剖析》——第8章,第8.6节键值存储同步

8.6 键值存储同步 iOS组件与框架--iOS SDK高级特性剖析 iCloud还支持键值存储同步.这类似于在NSMutableDictionary或NSUserDefaults中存储信息,将一个与对象值相关联的键用于存储和检索:iCloud键值存储的不同之处在于,将自动在设备之间同步键和值.本书编写期间,iCloud为每个应用提供1MB的键值存储空间,最多可存储1024个键值对,因此键值存储机制只适合用于存储少量信息. 本章的示例应用利用iCloud键值存储来跟踪最后修改的备忘录.详细视图控

PHP面向对象程序设计高级特性详解(接口,继承,抽象类,析构,克隆等)_php技巧

本文实例讲述了PHP面向对象程序设计高级特性.分享给大家供大家参考,具体如下: 静态属性 <?php class StaticExample { static public $aNum = 0; // 静态共有属性 static public function sayHello() { // 静态共有方法 print "hello"; } } print StaticExample::$aNum; StaticExample::sayHello(); ?> 输出:0