一、缺省模板参数

回顾前面的文章,都是自己管理stack的内存,无论是链栈还是数组栈,能否借助标准模板容器管理呢?答案是肯定的,只需要多传一个模板参数即可,而且模板参数还可以是缺省的,如下:

template <typename T, typename CONT = std::deque<T> >
class Stack
{

private:

CONT c_;
};

如果没有传第二个参数,默认为deque 双端队列,当然我们也可以传递std::vector<T>

下面程序借助标准模板容器管理内存来实现stack模板类:

Stack.h:

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
#ifndef _STACK_H_
#define _STACK_H_

#include <exception>
#include <deque>
using  namespace std;

template < typename T,  typename CONT = deque<T> >
class Stack
{
public:
    Stack() : c_()
    {
    }
    ~Stack()
    {
    }

void Push( const T &elem)
    {
        c_.push_back(elem);
    }
     void Pop()
    {
        c_.pop_back();
    }
    T &Top()
    {
         return c_.back();
    }
     const T &Top()  const
    {
         return c_.back();
    }
     bool Empty()  const
    {
         return c_.empty();
    }
private:
    CONT c_;
};

#endif  // _STACK_H_

main.cpp:

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
#include  "Stack.h"
#include <iostream>
#include <vector>
using  namespace std;

int main( void)
{
     /*Stack<int> s;*/
    Stack< int, vector< int> > s;
    s.Push( 1);
    s.Push( 2);
    s.Push( 3);

while (!s.Empty())
    {
        cout << s.Top() << endl;
        s.Pop();
    }
     return  0;
}

输出为 3 2 1

即如果没有传递第二个参数,堆栈和压栈等操作直接调用deque<int> 的成员函数,也由deque<int> 管理内存。

如程序中传递vector<int> ,则由vector<int> 成员函数处理。

二、成员模板

来看下面的例子:

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
#include <iostream>
using  namespace std;

template < typename T>
class MyClass
{
private:
    T value;
public:
     void Assign( const MyClass<T> &x)
    {
        value = x.value;
    }
};

int main( void)
{
    MyClass< double> d;
    MyClass< int> i;

d.Assign(d);         // OK
    d.Assign(i);         // Error
     return  0;
}

因为i 和 d 的类型不同,故会编译出错。可以用成员模板的方法解决:
C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 
#include <iostream>
using  namespace std;

template < typename T>
class MyClass
{
private:
    T value;
public:
    MyClass() {}
     template < class X>
    MyClass( const MyClass<X> &x) : value(x.GetValue())
    {

}
     template < class X>
     void Assign( const MyClass<X> &x)
    {
        value = x.GetValue();
    }
    T GetValue()  const
    {
         return value;
    }
};

int main( void)
{
    MyClass< double> d;
    MyClass< int> i;
    d.Assign(d);         // OK
    d.Assign(i);         // OK

MyClass< double> d2(i);

return  0;
}

为了支持  MyClass<double> d2(i); 故也要将拷贝构造函数实现为成员模板,同理,如果想支持 d = i ; 也要讲赋值运算符实现为成员
模板。 实际上auto_ptr<class> 中的实现就使用了成员模板,因为要支持类似下面的运算:
auto_ptr<X> x;
auto_ptr<Y> y;
x = y;
三、typename 关键字
看下面的例子:
C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
#include <iostream>
using  namespace std;

template < typename T>
class MyClass
{
private:
     typename T::SubType *ptr_;
};

class Test
{
public:
     typedef  int SubType;
};
int main( void)
{
    MyClass<Test> mc;
     return  0;
}

typename T::SubType *ptr_; 如果前面没有typename 修饰,则SubType会被认为是T类型内部的静态数据成员,推导下去,* 就不再认
为是指针,而被认为是乘号,编译的时候就出错了。加上修饰,就知道SubType 是T 内部的自定义类型,ptr是指向这种类型的指
针,编译通过。

四、派生类与模板、面向对象与泛型编程

(一)、派生类与模板

1、为了运行的效率,类模板是相互独立的,即独立设计,没有使用继承的思想。对类模板的扩展是采用适配器(adapter)来完成的。通用性是模板库的设计出发点之一,这是由泛型算法(algorithm)和函数对象(functor)等手段达到的。

2、派生的目标之一也是代码的复用和程序的通用性,最典型的就是MFC,派生类的优点是可以由简到繁,逐步深入,程序编制过程中可以充分利用前面的工作,一步步完成一个复杂的任务。

3、模板追求的是运行效率,而派生追求的是编程的效率。

(二)、面向对象与泛型编程

1、面向对象与泛型都依赖于某个形式的多态

面向对象

动态多态(虚函数)

泛型

静态多态(模板类,模板函数)

2、面向对象中的多态在运行时应用存在继承关系。我们编写使用这些类的代码,忽略基类与派生类之间的类型差异。只要使用基类指针或者引用,基类类型对象、派生类类型对象就可以共享相同的代码。

3、在泛型编程中,我们所编写的类和函数能够多态地用于编译时不相关的类型。一个类或一个函数可以用来操纵多种类型的对象。

参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范

从零开始学C++之模板(三):缺省模板参数(借助标准模板容器实现Stack模板)、成员模板、关键字typename...相关推荐

  1. 一个模板三种风格版本人物头像照片墙动态开场视频PR片头模板(含相同效果的AE模板)

    一个模板三种风格版本人物头像照片墙动态开场视频PR片头模板(含相同效果的AE模板) 项目特色: Adobe Premiere Pro CC 2020或更高版本 必须安装Adobe After Effe ...

  2. 从零开始学CIRCOS绘制圈图(三)

    这一篇会在 从零开始学CIRCOS绘制圈图(二)基础上开始在circos绘制基因密度信息.为了保证一致性,可以新建如下几个文件 circos.conf: karyotype = karyotype.t ...

  3. 从零开始学ESP32:(三)ESP32的蓝牙GATT服务测试

    从零开始学ESP32:个人笔记记录: 芯片型号: ESP32 网络环境支持:LWIP IDF.PY-SDK: ESP-IDF v4.3 芯片功能: 支持STA/AP网络共存模式: 参考工程:esp-i ...

  4. 从零开始学ios开发(三):第一个有交互的app

    感谢大家的关注,也给我一份动力,让我继续前进.有了自己的家庭有了孩子,过着上有老下有小的生活,能够挤出点时间学习真的很难,每天弄好孩子睡觉已经是晚上10点左右了,然后再弄自己的事情,一转眼很快就到12 ...

  5. C语言学习——从零开始学编程(第三篇:选择与循环)

    文章目录 前言--小颖的话 一.语句 1)C语言中的语句有哪些 2)语句 二.选择语句 1) if选择语句 1. if语句 2.if-else语句 3.if - else if - else 多分支语 ...

  6. shell 删除了hdfs 文件_从零开始学大数据(三) Shell操作HDFS文件系统-中

    1.格式化 [root@master sbin]# hdfs namenode -format 2.命令hdfs dfsadmin 查看(hdfs dfsadmin -report) [root@ma ...

  7. python画circos图_从零开始学CIRCOS绘制圈图(四)

    从零开始学CIRCOS绘制圈图(一) 从零开始学CIRCOS绘制圈图(二) 从零开始学CIRCOS绘制圈图(三) 通常circos的中间部分不是空白区域,会用一条条线进行连接,表示两个染色体部分区域有 ...

  8. 从零开始学 Web 系列教程

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新-- github:https://github.com/Daotin/Web 微信公众号:前端队长 博客园:http://ww ...

  9. arcgis mxt模板 创建工具条无法保存_【从零开始学GIS】ArcGIS中的绘图基本操作(二)...

    大家好,我是肝教程肝到熊猫眼的三三. 本系列教程的发布,受到了很多同学的鼓励,大家在后台或微信上表达出对教程的喜爱,这便是更新教程的最大动力. 上回教程讲解了"GIS基本操作".& ...

最新文章

  1. loguru log 日志的使用
  2. 【转】VS2008制作打包程序将安装路径写入注册表
  3. 自动加载 autoload
  4. 想做“冲顶大会”?全球首套直播竞答解决方案来了!
  5. sql和sqlite常用查询语句
  6. Nginx学习之十二-负载均衡-加权轮询策略剖析
  7. linux系统下聊天工具,linux系统环境下如何使用amsn聊天工具_linux教程
  8. Debian Chroot on Synology NAS
  9. 数据结构——>单向环形链表
  10. 《软件创富----共享软件创业之道》读后感
  11. C++解压KRC文件
  12. MICRO USB引脚定义以及接法
  13. HEVC/H.265与AVC/H.264对比总结
  14. 呼吸系统疾病病人的护理题库【2】
  15. 安装torch 时,bash install-deps错误
  16. 视频技术系列 - 谈谈毫米波
  17. Allegro删除Out of data shape铜皮框
  18. 数模国赛备赛(1)元胞自动机CA 生命游戏 森林火灾 传染病模型 MATLAB版资源整理
  19. PUN☀️七、网络同步:Object Synchronization
  20. TSMaster1.4.2补丁包发布

热门文章

  1. 581. 最短无序连续子数组 golang
  2. Linux的sort命令用法
  3. 守护进程nohup的用法
  4. 数据结构之空间复杂度和空间复杂度
  5. 二叉树的广度优先遍历(层序遍历)
  6. 处理大并发之二 对epoll的理解,epoll客户端服务端代码
  7. 引入宽字符error: converting to execution character set: Invalid or incomplete multibyte or wide character
  8. 【计算机系统设计】实践笔记(3)改进数据通路:jr指令分析与实现
  9. 【数字逻辑入门】计算机如何存储1位二进制数
  10. 不看绝对血亏!java字符串转json