用过Python的码友都知道,Python中List支持多种数据类型,如下面代码所示链表li内的数据类型可以是整数,同时也可以是字符串,当然也可以是其他数据类型。

   1: >>> li = [1,2.5,"hello world"]

   2: >>> li

   3: [1, 2.5, 'hello world']

   4: >>> 

对于一个C++爱好者来说,不由得想C++中是不是也有类似的容器或者方法来实现一个链表内可以支持多种数据类型呢?答案是肯定的。boost内有现成的类可以使用,但是我们先不着急看这个现成类的使用,看看能用几种方法来实现?

基本思路是模板+继承

实现方法一

将链表节点中的数据类型template参数化(如下):

   1: template<typename DataType>

   2: class Node {

   3: private:

   4:     DataType data;

   5:     ??? *next;

   6: }

可是next节点的数据类型可能跟当前node的数据类型不同,那可怎么定义呢?不同的数据类型需要同样的接口,自然想到用“继承”的方法来解决,多说无益,上图,上代码:

   1:  

   2: class NodeBase {

   3: ...

   4: private:

   5:   NodeBase *next; 

   6: };

   7:  

   8: template<typename DataType>

   9: class Node: public NodeBase {

  10: ...

  11: private:

  12:   DataType data;

  13: };

这样,当需要存入多个数据类型时,就会有相应的节点类型产生(例如,我们有三种类型int, double, string):

 

测试代码如下:

   1: class NodeBase {

   2:   friend class List;

   3:   friend ostream& operator<<(ostream &out, const List &list);

   4: public:

   5:   NodeBase() : next(NULL) {}

   6:   virtual ~NodeBase() {}

   7:  

   8:   virtual void operator<<(ostream &out) = 0;

   9:  

  10: private:

  11:   NodeBase *next; 

  12: };

  13:  

  14: ///

  15: ///template class to create Node type based on data type

  16: ///

  17: template<typename DataType>

  18: class Node: public NodeBase {

  19:   friend class List;

  20: public:

  21:   Node(const DataType &idata): data(idata){}

  22:  

  23:   virtual void operator<<(ostream &out)

  24:   {

  25:     out<<data;

  26:   }

  27:  

  28: private:

  29:   DataType data;

  30: };

  31:  

  32: class List

  33: {

  34:   friend ostream& operator<<(ostream &out, const List &list);

  35: public:

  36:   List()

  37:   {

  38:     head = tail = NULL;

  39:   }

  40:   ~List()

  41:   {

  42:     for (; head;) {

  43:       NodeBase *next = head->next;

  44:       delete head;

  45:       head = next;

  46:     }

  47:     tail = NULL;

  48:   }

  49:  

  50:   ///

  51:   ///template function to add a new node

  52:   ///based on the input data type, to determine

  53:   ///the node type

  54:   ///

  55:   template <typename DataType>

  56:   void add(const DataType &data)

  57:   {

  58:     NodeBase *node = new Node<DataType>(data);

  59:     if (!tail) {

  60:       head = node;

  61:     }

  62:     else {

  63:       tail->next = node;

  64:     }

  65:     tail = node;

  66:   }

  67:  

  68: private:

  69:   NodeBase *head, *tail;

  70: };

  71:  

  72: ///

  73: ///test to output all datas in the input @a list 

  74: ///

  75: ostream& operator<<(ostream &out, const List &list)

  76: {

  77:   for (NodeBase *node = list.head; node; node = node->next)

  78:   {

  79:     node->operator<<(out);

  80:     out<<' ';

  81:   }

  82:   return out;

  83: }

  84:  

  85: ///

  86: ///test a list support multiple data types just like Python

  87: ///

  88: int main()

  89: {

  90:  

  91:   List *list = new List;

  92:  

  93:   list->add(1);

  94:   list->add(2.5);

  95:   list->add(string("hello world"));

  96:  

  97:   cout<<*list<<endl;

  98:   

  99:   delete list; list = NULL;

 100:   return 0;

 101: }

实现方法二

用一个抽象数据类型作为接口,直接上图:

 

   1: class DataBase {

   2: ...

   3: };

   4:  

   5: template <typename InnerType>

   6: class Data : public DataBase {

   7: public:

   8:   Data(const InnerType &idata) : innerData(idata)  {}

   9: ...

  10: private:

  11:     InnerType innerData;

  12: };

  13:  

  14: class Node {

  15: public:

  16:   template <typename InnerType>

  17:   Node(const InnerType &idata)

  18:     : data(new Data<InnerType>(idata)), next(NULL) {}

  19:   ~Node()

  20:   {

  21:     delete data; data = NULL;

  22:   }

  23:  

  24: private:

  25:   DataBase *data;

  26:   Node     *next;

  27: };

测试代码如下:

   1:  

   2: #include <iostream>

   3:  

   4: using namespace std;

   5:  

   6: class List;

   7:  

   8: class DataBase {

   9: public:

  10:   virtual ~DataBase() {}

  11:  

  12:   virtual void operator<<(ostream &out) = 0;

  13: };

  14:  

  15: template <typename InnerType>

  16: class Data : public DataBase {

  17: public:

  18:   Data(const InnerType &idata) : innerData(idata)  {}

  19:  

  20:   virtual void operator<<(ostream &out)

  21:   {

  22:     out<<innerData;

  23:   }

  24: private:

  25:     InnerType innerData;

  26: };

  27:  

  28: ///

  29: ///template class to create Node type based on data type

  30: ///

  31: class Node {

  32:   friend class List;

  33:   friend ostream& operator<<(ostream &out, const List &list);

  34: public:

  35:   template <typename InnerType>

  36:   Node(const InnerType &idata)

  37:     : data(new Data<InnerType>(idata)), next(NULL) {}

  38:   ~Node()

  39:   {

  40:     delete data; data = NULL;

  41:   }

  42:  

  43: private:

  44:   DataBase *data;

  45:   Node     *next;

  46: };

  47:  

  48: class List

  49: {

  50:   friend ostream& operator<<(ostream &out, const List &list);

  51: public:

  52:   List()

  53:   {

  54:     head = tail = NULL;

  55:   }

  56:   ~List()

  57:   {

  58:     for (; head;) {

  59:       Node *next = head->next;

  60:       delete head;

  61:       head = next;

  62:     }

  63:     tail = NULL;

  64:   }

  65:  

  66:   ///

  67:   ///template function to add a new node

  68:   ///based on the input data type, to determine

  69:   ///the node type

  70:   ///

  71:   template <typename InnerType>

  72:   void add(const InnerType &data)

  73:   {

  74:     Node *node = new Node(data);

  75:     if (!tail) {

  76:       head = node;

  77:     }

  78:     else {

  79:       tail->next = node;

  80:     }

  81:     tail = node;

  82:   }

  83:  

  84: private:

  85:   Node *head, *tail;

  86: };

  87:  

  88: ///

  89: ///test to output all datas in the input @a list 

  90: ///

  91: ostream& operator<<(ostream &out, const List &list)

  92: {

  93:   for (Node *node = list.head; node; node = node->next)

  94:   {

  95:     if (node->data) {

  96:       node->data->operator<<(out);

  97:       out<<' ';

  98:     }

  99:   }

 100:   return out;

 101: }

 102:  

 103: ///

 104: ///test a list support multiple data types just like Python

 105: ///

 106: int main()

 107: {

 108:  

 109:   List *list = new List;

 110:  

 111:   list->add(1);

 112:   list->add(2.5);

 113:   list->add(string("hello world"));

 114:  

 115:   cout<<*list<<endl;

 116:   

 117:   delete list; list = NULL;

 118:   return 0;

 119: }

实现方法三

boost::any,关于它的介绍,这个博客不错:http://blog.csdn.net/hityct1/article/details/4186962,感兴趣的码友可以去深入了解。

 

参考文献

http://stackoverflow.com/questions/17528657/python-list-equivalent-in-c

http://www.cnblogs.com/kex1n/archive/2011/04/11/2013098.html

http://blog.csdn.net/debugm/article/details/8241759

http://www.360doc.com/content/14/0103/17/15099545_342367928.shtml

http://blog.csdn.net/hityct1/article/details/4186962

【原创】C++链表如何像Python List一样支持多种数据类型的更多相关文章

  1. python入门(8)数据类型和变量

    python入门(8)数据类型和变量 数据类型 在Python中,能够直接处理的数据类型有以下几种: 整数 Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样 ...

  2. 我的Python学习之路 Python的输入输出与基本数据类型

    *** python中的变量不需要事先声明再使用,而可以直接来一个变量名,后面一个赋值,接着一个数据值,如 hw = "hello python",相当于Python能智能的根据你 ...

  3. 用 Python 排序数据的多种方法

    用 Python 排序数据的多种方法 目录 [Python HOWTOs系列]排序 Python 列表有内置就地排序的方法 list.sort(),此外还有一个内置的 sorted() 函数将一个可迭 ...

  4. 【转】让Souce Insight支持多种语言的语法高亮:Python,Ruby,ARM汇编,windows脚本文件(bat/batch),PPC,SQL,TCL,Delphi等

    原文网址:http://www.crifan.com/source_insight_support_highlight_for_python_ruby_arm_batch_ppc_sql_tcl_de ...

  5. Python学习笔记:02数据类型

    Python 数据类型 python中标准的数据类型有 基础类型 整型(长整型) 浮点型 复数型 布尔型 序列类型 字符串 列表 元组 字典 整型 整型和长整型并不严格区分,整型int的表达范围和计算 ...

  6. Python自动化开发-变量、数据类型和运算

    一.变量 变量定义:Variables are used to store infomation to referrenced and manipulated in a computer progra ...

  7. Python第三天 序列 数据类型 数值 字符串 列表 元组 字典

    Python第三天 序列  数据类型  数值  字符串  列表  元组  字典 数据类型数值字符串列表元组字典 序列序列:字符串.列表.元组序列的两个主要特点是索引操作符和切片操作符- 索引操作符让我 ...

  8. python学习日记(基础数据类型及其方法01)

    数字 int 主要是用于计算的,常用的方法有一种 #既十进制数值用二进制表示时,最少使用的位数i = 3#3的ASCII为:0000 0011,即两位 s = i.bit_length() print ...

  9. python的6种基本数据类型--字典

    python的6种基本数据类型--字典   字典 字典的定义与特性 字典是Python语言中唯一的映射类型. 定义:{key1:value1,key2:value2} 1.键与值用冒号":& ...

随机推荐

  1. oracle学习 十 数据库的语句优化(持续更)

    平时关注Oracle数据库的网友都知道,Oracle性能优化保证了Oracle数据库的健壮性.下面就此提出需要注意的两个原则.   原则一:注意WHERE子句中的连接顺序: ORACLE采用自下而上的 ...

  2. 移动端页面的head头部内容

  3. 【Android框架进阶〖0〗】ThinkAndroid注解机制

    由于项目需要,开始研究ThinkAndroid. 个人认为该框架的注解机制十分新颖,所以先研究这个,顺便学习下 Java 的annotation. 粗略的看了看,该机制在BaseActivity中初始 ...

  4. 在Ribbon中,中文换行位置不对怎么办

    在Ribbon代码的编写时,关于UI上面设置Button的中文字,经常会出现不想换行的地方换行的情况,比如下图: 我如果希望中国一行,然后只有一行怎么办呢. 网上流传的很多方法就是直接加空格,但是很遗 ...

  5. (VC)解决绘图时闪烁问题的一点经验[转]

    转自:http://www.cnblogs.com/lidabo/p/3429862.html 清除屏幕闪烁 (转自网上) <一> 由于作图过于复杂和频繁,所以时常出现闪烁的情况,一些防止 ...

  6. (剑指Offer)面试题34:丑数

    题目: 把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含因子7. 习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第N个丑数. 思路: 1. ...

  7. 远程调用WMI安装软件

     Invoke-WMIMethod  -ComputerName $ip -Credential $cred -path Win32_product -Name Install -ArgumentLi ...

  8. Microsoft.AlphaImageLoader滤镜解说

    Microsoft.AlphaImageLoader是IE滤镜的一种,其主要作用就是对图片进行透明处理.尽管FireFox和IE7以上的IE浏览器已经支持透明的PNG图片,可是就IE5-IE6而言还是 ...

  9. [译]如何在Unity编辑器中添加你自己的工具

    在这篇教程中你会学习如何扩展你的Unity3D编辑器,以便在你的项目中更好的使用它.你将会学习如何绘制你自己的gizmo,用代码来实现创建和删除物体,创建编辑器窗口,使用组件,并且允许用户撤销他们所作 ...

  10. LFS7.4编译笔记(1)

    由于第一次编译,花了不少时间,也不知道能不能成功,所以就没有记笔记,现在重新编译一次,这次不装U盘而是装到我的移动硬盘上面.步骤差不多,因为我感觉硬盘的速度会比U盘快. 至于LFS的优点,我就不多说了 ...