您的位置:首页 > 编程语言 > C语言/C++

【原创】C++链表如何像Python List一样支持多种数据类型

2014-03-22 22:43 746 查看

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

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


>>> li


[1, 2.5, 'hello world']


>>>


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

基本思路是模板+继承

实现方法一

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

template<typename DataType>


class Node{


private:


DataType data;


??? *next;


}


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





 


class NodeBase{


...


private:


NodeBase *next;


};


 


template<typename DataType>


class Node: public NodeBase{


...


private:


DataType data;


};


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





 

测试代码如下:

class NodeBase{


friendclass List;


friendostream& operator<<(ostream &out, const List &list);


public:


NodeBase() : next(NULL){}


virtual ~NodeBase(){}


 


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


 


private:


NodeBase *next;


};


 


///


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


///


template<typename DataType>


class Node: public NodeBase{


friendclass List;


public:


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


 


virtual void operator<<(ostream &out)


{


out<<data;


}


 


private:


DataType data;


};


 


class List


{


friendostream& operator<<(ostream &out, const List &list);


public:


List()


{


head = tail = NULL;


}


~List()


{


  for (; head;){


NodeBase *next = head->next;


delete head;


head = next;


}


tail = NULL;


}


 


///


///template function to add a new node


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


///the node type


///


template <typename DataType>


void add(const DataType &data)


{


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


  if (!tail){


head = node;


}


  else{


tail->next = node;


}


tail = node;


}


 


private:


NodeBase *head, *tail;


};


 


///


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


///


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


{


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


{


node->operator<<(out);


out<<' ';


}


return out;


}


 


///


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


///


int main()


{


 


List *list = new List;


 


list->add(1);


list->add(2.5);


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


 


cout<<*list<<endl;




delete list; list = NULL;


return 0;


}


实现方法二

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





 

 class DataBase{


...


};


 


template <typename InnerType>


 class Data : public DataBase{


public:


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


...


private:


  InnerType innerData;


};


 


class Node{


public:


template <typename InnerType>


Node(const InnerType &idata)


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


~Node()


{


  delete data; data = NULL;


}


 


private:


DataBase *data;


Node  *next;


};


测试代码如下:

 


#include <iostream>


 


using namespace std;


 


class List;


 


 class DataBase{


public:


virtual ~DataBase(){}


 


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


};


 


template <typename InnerType>


 class Data : public DataBase{


public:


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


 


virtual void operator<<(ostream &out)


{


  out<<innerData;


}


private:


  InnerType innerData;


};


 


///


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


///


class Node{


friendclass List;


friendostream& operator<<(ostream &out, const List &list);


public:


template <typename InnerType>


Node(const InnerType &idata)


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


~Node()


{


  delete data; data = NULL;


}


 


private:


DataBase *data;


Node  *next;


};


 


class List


{


friendostream& operator<<(ostream &out, const List &list);


public:


List()


{


head = tail = NULL;


}


~List()


{


  for (; head;){


 Node *next = head->next;


delete head;


head = next;


}


tail = NULL;


}


 


///


///template function to add a new node


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


///the node type


///


template <typename InnerType>


void add(const InnerType &data)


{


  Node *node = new Node(data);


  if (!tail){


head = node;


}


  else{


tail->next = node;


}


tail = node;


}


 


private:


Node *head, *tail;


};


 


///


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


///


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


{


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


{


  if (node->data){


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


  out<<' ';


}


}


return out;


}


 


///


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


///


int main()


{


 


List *list = new List;


 


list->add(1);


list->add(2.5);


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


 


cout<<*list<<endl;




delete list; list = NULL;


return 0;


}


实现方法三

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

 

参考文献

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

/article/4715401.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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: