variant list同样基于简单链表,不同结点的元素不同但是为了能够链表元素的插入和读取,必须提供相同的接口,所以可以通过继承还保持相同的接口,通过多态来保证各个结点元素的输出。
这一举一个简单的例子--冰糖葫芦。冰糖葫芦是经典的小吃,传统的冰糖葫芦统一由山楂串联而成,类似于list,而在现实生活中我们经常能看到串橘子的、苹果的、甚至黄瓜的冰糖葫芦,这就类似于我们的chunk list。这里我们假设能够做冰糖葫芦的东西都为水果,山楂、苹果、橘子都认为是水果所以才能做冰糖葫芦。那么水果就是冰糖葫芦统一的接口,每个冰糖葫芦的结点都要提供一个水果这样的接口,同时要延伸出去一个水果的link去串联下一个水果。同时每种水果都要可以展示出自己是什么水果的接口函数,通过父类水果的指针实现对其的调用,这就是多态的作用。
#include<iostream> class Fruit { friend class Bingtanghulu; protected: std::string name; std::string color; double price; Fruit* link; Fruit(std::string n, std::string c, double p) :name(n),color(c),price(p) { link = 0; } virtual void display()const; virtual Fruit* getnode(){} }; class Hawthorn:public Fruit { friend class Bingtanghulu; protected: std::string taste; public: Hawthorn(std::string n, std::string c, double p, std::string t) :Fruit(n, c, p),taste(t) {} void display()const; Fruit* getnode(); }; class Orange:public Fruit { friend class Bingtanghulu; protected: std::string smell; public: Orange(std::string n, std::string c, double p, std::string s) :Fruit(n, c, p),smell(s) {} void display()const; Fruit* getnode(); }; class Apple:public Fruit { friend class Bingtanghulu; protected: std::string size; public: Apple(std::string n, std::string c, double p, std::string s) :Fruit(n, c, p),size(s) {} void display()const; Fruit* getnode(); }; class Bingtanghulu { private: Fruit* head; public: Bingtanghulu() { head = new Fruit("tanghulu","red",10.0); } ~Bingtanghulu() { delete head; } void Display()const; bool Delete(std::string name); void Insert(Fruit* fruit); };
#include<iostream> #include"variant_list.h" void Fruit::display()const { std::cout<<"i am a fruit"<<std::endl; } void Hawthorn::display()const { std::cout<<" Hawthorn "<<std::endl; } Fruit* Hawthorn::getnode() { return this; } void Orange::display()const { std::cout<<" Orange"<<std::endl; } Fruit* Orange::getnode() { return this; } void Apple::display()const { std::cout<<" Apple"<<std::endl; } Fruit* Apple::getnode() { return this; } void Bingtanghulu::Display()const { Fruit* hulu = head->link; while(hulu) { std::cout<<" | "<<std::endl; std::cout<<" | "<<std::endl; hulu->display(); hulu = hulu->link; } std::cout<<" | | "<<std::endl; std::cout<<" | | "<<std::endl; std::cout<<" "<<std::endl; } void Bingtanghulu::Insert(Fruit* fruit) { Fruit* hulu = head; while(hulu->link) { hulu = hulu->link; } hulu->link = fruit->getnode(); hulu = hulu->link; hulu->link = 0; } bool Bingtanghulu::Delete(std::string name) { Fruit *hu = head, *lu = head->link; while(lu && lu->name != name) { hu = lu; lu = lu->link; } if(lu) { hu->link = lu->link; return 1; } else { return 0; } }
在此基础上,我们可以将chunk list 进行改进实现一个通用版的variant list,它的原理与冰糖葫芦一样,通过模板类继承一个基类产生统一的接口,通过虚函数实现打印内部数据的多态。需要注意的是模板类的成员函数的实现应在.h文件中。#include"variant_list.h" int main() { Bingtanghulu tanghulu; Hawthorn shanzha("shanzha","red",5.0,"sweet"); Orange juzi("juzi","yellow",3.0,"sugar"); Apple pingguo("pingguo","red",5.0,"big"); std::cout<<"hello world"<<std::endl; tanghulu.Insert(&shanzha); std::cout<<"hello world"<<std::endl; tanghulu.Insert(&juzi); tanghulu.Insert(&pingguo); tanghulu.Display(); tanghulu.Delete("juzi"); tanghulu.Display(); tanghulu.Delete("pingguo"); tanghulu.Display(); tanghulu.Delete("shanzha"); tanghulu.Display(); return 0; }
#include<iostream> #include<vector> #include<cstddef> class Basenode { friend class VariantList; protected: Basenode* link; public: Basenode() :link(0) {} ~Basenode(){} virtual void display()const {} virtual Basenode* getnode() { return 0; } }; template<typename T> class Derivednode:public Basenode { protected: std::vector<T> vec; public: Derivednode(T* buffer, size_t size) :vec(buffer, buffer+size) {} ~Derivednode(){}; void display()const; Basenode* getnode(); }; class VariantList { private: Basenode* head; public: VariantList() { head = new Basenode; } ~VariantList() { delete head; } void InsertList(Basenode* bnode); void DisplayList()const; }; template<typename T> void Derivednode<T>::display()const { for(typename std::vector<T>::const_iterator iter = vec.begin(); iter != vec.end(); ++iter) { std::cout<<*iter<<"\t"; } std::cout<<std::endl; } template<typename T> Basenode* Derivednode<T>::getnode() { return this; }
#include"variant_list2.h" void VariantList::InsertList(Basenode* bnode) { Basenode* p = head; while(p->link) { p = p->link; } p->link = bnode->getnode(); p->link->link = 0; } void VariantList::DisplayList()const { const Basenode* p = head; while(p->link) { p = p->link; p->display(); } }
#include"variant_list2.h" #include<iostream> int main() { int a[]={1,2,3}; char b[]={'a','b','c','d'}; std::string s[]={"hello","world"}; Derivednode<int> intnode(a, 3); Derivednode<char> charnode(b, 4); Derivednode<std::string> stringnode(s, 2); VariantList vl; vl.InsertList(&intnode); vl.InsertList(&charnode); vl.InsertList(&stringnode); vl.DisplayList(); return 0; }