首页 > 代码库 > 可回收重复使用的链表,类似于Android消息链(并记录多态使用)

可回收重复使用的链表,类似于Android消息链(并记录多态使用)

在尾部生产,头部消耗的链表,数据增加可重复使用的功能。

新数据类型继承Nod,实现newNod方法即可。使用时没有模板那么方便,需要强转。

感觉newNod和Windows好多结构体有个表示结构体大小的成员主要告诉new多大,使用时强转和CPtrList差不多。感觉这样设计也没啥不妥。

 回顾C++

 

// Demo.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include<stdio.h>#include <tchar.h>#include<windows.h>//为了 CRT 函数能够正常工作,#include 语句必须遵循此处所示的顺序。//包含 crtdbg.h,将 malloc 和 free 函数映射到它们的调试版本,即 _malloc_dbg 和 free,它们将跟踪内存分配和释放。 //此映射只在包含 _DEBUG 的调试版本中发生。 发布版本使用普通的 malloc 和 free 函数。//#define 语句将 CRT 堆函数的基础版本映射到对应的调试版本。 如果省略 #define 语句,内存泄漏转储将有所简化。//使用这些语句启用调试堆函数之后,可以在某个应用程序退出点之前设置一个对 _CrtDumpMemoryLeaks 的调用,以便在应用程序退出时显示内存泄漏报告:#define _CRTDBG_MAP_ALLOC#include <stdlib.h>#include <crtdbg.h>//不过,如果程序使用 C++ new 运算符分配内存,则需要重新定义 new 才能在内存泄漏报告中看到文件和行号。 您可以利用如下所示的代码块实现:#ifdef _DEBUG#ifndef DBG_NEW#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )#define new DBG_NEW#endif#endif  // _DEBUG#define CFREE(pPointer) if(pPointer){\    ::free(pPointer);     pPointer = NULL; }//_MSC_VER是MSVC编译器的内置宏,定义了编译器的版本。下面是一些编译器版本的_MSC_VER值//MS VC++ 10.0 _MSC_VER = 1600//MS VC++ 9.0 _MSC_VER = 1500//MS VC++ 8.0 _MSC_VER = 1400//MS VC++ 7.1 _MSC_VER = 1310//MS VC++ 7.0 _MSC_VER = 1300//MS VC++ 6.0 _MSC_VER = 1200//MS VC++ 5.0 _MSC_VER = 1100#if _MSC_VER <= 1200#ifndef __STDC_WANT_SECURE_LIB__#define sprintf_s sprintf#define _stricmp stricmp#endif#endiftemplate<class Type>struct TypedNod{    Type info;    TypedNod<Type>* next;};class Nod{public:    Nod *next;    //C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为虚函数重写。    //重写的话可以有两种,直接重写成员函数和重写虚函数,只有重写了虚函数的才能算作是体现了C++多态性    virtual Nod* newNod(){#ifdef _DEBUG        printf("-Nod::newNod();\n");#endif        return new Nod();    }    static Nod* newNod0(){#ifdef _DEBUG        printf("-Nod::newNod0();\n");#endif        return new Nod();    }    virtual void release(){#ifdef _DEBUG        printf("-Nod::release();\n");#endif    }    Nod(){#ifdef _DEBUG        printf("-Nod::Nod();\n");#endif        next = NULL;    }    virtual  ~Nod(){#ifdef _DEBUG        printf("-Nod::~Nod();\n");#endif    }};typedef Nod* NEWNODE(void);class FileNod : public Nod{public:    int mode;    long size;    char *path;    void setPath(const char *p){        path = strdup(p);    }    FileNod() :        path(NULL){#ifdef _DEBUG        printf("--FileNod::FileNod();\n");#endif    }    virtual ~FileNod(){#ifdef _DEBUG        printf("--FileNod::~FileNod();\n");#endif        release();    }    virtual Nod* newNod(){#ifdef _DEBUG        printf("--FileNod::newNod();\n");#endif        return new FileNod();    }    static Nod* newNod0(){#ifdef _DEBUG        printf("--FileNod::newNod0();\n");#endif        return new FileNod();    }    virtual void release(){#ifdef _DEBUG        printf("--FileNod::release();\n");#endif        CFREE(path);    }};/** 我们没有清空回收到recyledPool项的数据域各字段,所以不推荐使用旧值,小心访问里面的数据。类似于硬盘删除文件,实际上没有把数据域重写(也是硬盘恢复工具)。提高性能。*/class RecyledQueue{public:    Nod* header;    Nod* tailer;    int size;    //废弃消息池(链)(就是废品收购站)    Nod* recyledPool;protected:    //消息池当前大小    int recyledPoolSize;    // 消息池上限值    //static const int MAX_POOL_SIZE  = 50; //vc下不支持这样    const static int MAX_POOL_SIZE; // here initialize     Nod* hFactory;                //C++多态的应用    NEWNODE *pfnNewNodFactory;    //函数指针不必每次new实例public:    RecyledQueue(NEWNODE pfnNewNod) :        recyledPool(NULL), recyledPoolSize(0), header(NULL), tailer(NULL), size(0)    {        pfnNewNodFactory = pfnNewNod;    }    RecyledQueue(Nod* hNod) :        recyledPool(NULL), recyledPoolSize(0), header(NULL), tailer(NULL), size(0)    {        hFactory = hNod;    }    ~RecyledQueue() {        release(header, recyledPoolSize);        release(recyledPool, size);        //hFactory->release();        delete hFactory;        hFactory = NULL;        header = NULL;        tailer = NULL;        printf("RecyledQueue::~RecyledQueue();\n");    }    //删除链表结点其实很简单,一般用到三个结构体指针变量和一个循环结构。    void release(Nod* pNod, int& size) {        Nod* pNext;        while (pNod)        {            pNext = pNod->next; //q指向当前结点的下一个结点。            delete pNod; //::free(p); //释放当前结点            pNod = pNext; //p指向下一个结点            size--;        }    }    /**    * Return a new Message instance from the global pool. Allows us to avoid allocating new objects    * in many cases. 该函数内部首先是从全局的废弃消息池(链)中去取,看看有没有废弃掉的Message,如果有,那我们就获取消息链中第一个废弃掉的Message。    * 这样,就无需再创建一个新的Message;如果消息池中没有,那就只能new一个新的消息出来。这样做的好处就是废物再利用,减少创建时间。    * 实际上,这种思想很值得我们借鉴。对于其它重载版的obtain方法,内部都是先调用它,然后再使用其它额外的参数进行填充的。    */    Nod* obtain() {        if (recyledPool != NULL)        {            Nod* m = recyledPool;            recyledPool = m->next;            m->next = NULL;            recyledPoolSize--;            return m;        }        if (hFactory){#ifdef _DEBUG            printf("\n\n----hFactory->newNod();\n");#endif            return hFactory->newNod(); //C++多态的应用        }        else if (pfnNewNodFactory){#ifdef _DEBUG            printf("\n\n----pfnNewNodFactory();\n");#endif            return pfnNewNodFactory();        }        return NULL;    }    /**    * Return a Message instance to the global pool. You MUST NOT touch the Message after calling    * this function -- it has effectively been freed.    *    * @return    */    RecyledQueue* recycle(Nod* node) {        if (recyledPoolSize < MAX_POOL_SIZE)        {            //添加到消息链的头部            node->next = recyledPool;            //更新sPool指向当前            recyledPool = node;            recyledPoolSize++;        }        return this;    }    /**    * Unlinks non-null first node.    */    RecyledQueue* unlinkFirst() {        Nod* pTmpHeader = header;        if (NULL != pTmpHeader)        {            header = pTmpHeader->next;            pTmpHeader->next = NULL;            //after unlinking the first, it is empty.            if (header == NULL)            {                tailer = NULL;            }            size--;            recycle(pTmpHeader);        }        return this;    }    /**    * Links newNode as last element.    */    RecyledQueue* linkLast(Nod* newNode) {        if (newNode != NULL)        {            //This linkedList is a empty queue.            if (tailer == NULL)            {                header = newNode;            }            else            {                tailer->next = newNode;            }            tailer = newNode;            size++;        }        return this;    }};const int RecyledQueue::MAX_POOL_SIZE = 50;void PrintLastError(int errorno){#if defined(DEBUG) || defined(_DEBUG)    LPVOID    lpMsgBuf;    if (0 == errorno)    {        errorno = GetLastError();    }    /* dwFlags标志位,决定如何说明lpSource参数,dwFlags的低位制定如何处理换行功能在输出缓冲区,    也决定最大宽度的格式化输出行。    可选参数:    标志                                标志说明    FORMAT_MESSAGE_ALLOCATE_BUFFER        函数会分配一个足够大的缓冲区保存格式化消息,并且通过lpBuffer指向该地址。    FORMAT_MESSAGE_ARGUMENT_ARRAY        Arguments参数不是指向va_list结构体,但是是一个指向保存参数的数据。    FORMAT_MESSAGE_FROM_HMODULE            lpSource参数是需要去搜索的一个包含消息表的模块线程。如果lpSource是NULL,当前进程的    应用图像会被搜索,这个标志不能同FORMAT_MESSAGE_FROM_STRING使用。    FORMAT_MESSAGE_FROM_STRING            lpSource参数是一个指向以NULL结尾的字符串,字符串包含一个消息定义,这个消息定义可    以包含插入序列。此标志最好不要和FORMAT_MESSAGE_FROM_HMODULE或者    FORMAT_MESSAGE_FROM_SYSTEM使用    FORMAT_MESSAGE_FROM_SYSTEM            0x00001000    函数会为了请求的信息而搜索系统的消息表资源。如果标志同时也指定了    FORMAT_MESSAGE_FROM_HMODULE,那么函数会先在lpSource指定的模块中搜索请求的消息,    如果搜索不到,就去搜索系统消息表资源。此标志不能与FORMAT_MESSAGE_FROM_STRING使用。    FORMAT_MESSAGE_IGNORE_INSERTS        消息定义中的插入序列会被一直忽略和跳过直到输出缓冲区不改变,并且Arguments会被忽略。    */    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, 0, (LPTSTR)&lpMsgBuf, 0, NULL);#ifdef _CONSOLE    printf("(%d), %s\r\n", errorno, lpMsgBuf);#else    MessageBox(NULL, (LPCTSTR)lpMsgBuf, "错误", MB_OK | MB_TOPMOST);#endif    LocalFree(lpMsgBuf);#endif}void show_file(char path[], RecyledQueue* pQueue, int level = 0){    char findBuffer[256];    sprintf_s(findBuffer, "%s*", path);    WIN32_FIND_DATAA findFileData;    HANDLE hFind = FindFirstFileA(findBuffer, &findFileData);    if (hFind == INVALID_HANDLE_VALUE){        PrintLastError(GetLastError());        return;    }    char *pFileName = findFileData.cFileName;    while (FindNextFileA(hFind, &findFileData))    {        if (0 != _stricmp(pFileName, "..") && 0 != _stricmp(pFileName, "."))        {            FileNod* pFileNod = (FileNod*)pQueue->obtain();            //pFileNod->path = new char[strlen(pFileName)+1];            pFileNod->setPath(pFileName);            pQueue->linkLast(pFileNod);            pFileNod->size = findFileData.nFileSizeLow;            if (findFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)            {                pFileNod->mode = 1;                sprintf_s(findBuffer, "%s%s\\", path, findFileData.cFileName);                show_file(findBuffer, pQueue, level + 1);            }        }    }}#include<iostream>using namespace std;class Base{public:    void fptr()    {        printf("void Base::fptr()\n");    }    virtual void vfptr()    {        printf("virtual void Base::vfptr()\n");    }    void fptr_arg(int i)    {        printf("void Base::fptr_arg(int i = %d)\n", i);    }    void fptr_arg2(int i)    {        printf("void Base::fptr_arg2(int i = %d)\n", i);    }    virtual void vfptr_arg(int i)    {        printf("virtual void Base::vfptr_arg(int i = %d)\n", i);    }    virtual void vfptr_arg2(int i)    {        printf("virtual void Base::vfptr_arg2(int i = %d)\n", i);    }    virtual void vfptr_arg3(int i)    //派生类没有此同名函数    {        printf("virtual void Base::vfptr_arg2(int i = %d)\n", i);    }};class Derived : public Base{public:    void fptr()//隐藏-覆盖    {        printf("void Derived::fptr()\n");    }    void vfptr()//隐藏-多态、覆盖    {        printf("virtual void Derived::vfptr()\n");    }    void fptr_arg(int i)//隐藏(同参)-覆盖(2)        {        printf("void Derived::fptr_arg(int i = %d)\n", i);    }    void fptr_arg2(float f)//隐藏(不同参)-覆盖(1)由于继承类隐藏基类方法fptr_arg2(float),写代码时调不到基类同名方法的    {        printf("void Derived::fptr_arg2(float f = %f)\n", f);    }    virtual void vfptr_arg(int i)//隐藏(同参)-覆盖,会表现为运行时多态    {        printf("virtual void Derived::vfptr_arg(int i = %d)\n", i);    }    virtual void vfptr_arg2(float f)//隐藏(不同参)-覆盖,不会表现为运行时多态 (1)由于继承类隐藏基类方法vfptr_arg2(int),写代码时调不到基类同名方法的    {        printf("virtual void Derived::vfptr_arg2(float f = %f)\n", f);    }};int _tmain(int argc, _TCHAR* argv[]) {    {        //如果应用程序有多个退出点,并不需要在每个退出点都手动设置一个对 _CrtDumpMemoryLeaks 的调用。         //应用程序开头部分对 _CrtSetDbgFlag 的调用会导致在每个退出点自动调用 _CrtDumpMemoryLeaks。         //您必须设置两个位域,如下所示:        _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);        //new FileNod();        char* scanPath = "D:\\BaiduYunDownload\\";        printf("RecyledQueue queue(new FileNod())\n");        RecyledQueue queue(FileNod::newNod0);        //RecyledQueue queue(new FileNod());        printf("\n\n//-----------show_file starts.-----------\n");        show_file(scanPath, &queue);        printf("\n//-----------show_file ends.-----------\n\n\n");        FileNod *visitNode = (FileNod *)queue.header;        FileNod *lastNode = NULL;        FileNod *nextNode = NULL;        int i = 0;        while (visitNode) {            nextNode = (FileNod *)visitNode->next;            printf("%d : %s, %s, %d\n", i++, visitNode->path, (visitNode->mode ? "[Folder]" : "[File]"), visitNode->size);            queue.unlinkFirst();            visitNode = (FileNod *)nextNode;        }        i = 0;        visitNode = (FileNod *)queue.recyledPool;        printf("\n\n\n//------------------------------------------------\n\n\n");        while (visitNode) {            printf("%d : %s, %s, %d\n", i++, visitNode->path, (visitNode->mode ? "[Folder]" : "[File]"), visitNode->size);            visitNode = (FileNod *)visitNode->next;        }    }//Esape queue  ~RecyledQueue().    _CrtDumpMemoryLeaks();    printf("\n\n\n//------------------------------------------------\n\n\n");    Base a;    Derived b;    printf("----Base *p = &a; //ok------------------------------------\n");    Base *p = &a;    p->fptr();    //void A::fptr()    p->vfptr();  //virtual void A::vfptr()    printf("----Base *p = &b; //ok------------------------------------\n");    p = &b;    p->fptr();    //void A::fptr()        p->vfptr();  //virtual void B::vfptr()    printf("----Derived *ptr = (Derived *)&a; //cast nosecury------------------------\n");    Derived *ptr = (Derived *)&a;    ptr->fptr();       //void B::fptr()        ptr->vfptr();  //virtual void A::vfptr()    //C++的隐藏 “隐藏”是指派生类的函数屏蔽了与其同名的基类函数    //(1)    如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆),即编译时符合基类参数而不符合派生类参数会报错。    //(2)    如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。        //C++多态性    //a、编译时多态性:通过重载函数实现     //b、运行时多态性:通过虚函数实现。即,条件:函数同名同参和带有关键字virtual。    //无virtual关键字,编译时确定,根据指针类型。    //有virtual关键字,运行时确定,根据指针指向的实际内容类型。    //参数不同算重载    printf("\n\n----Derived d; Base *pb = &d; Derived *pd = &d;---------------\n\n");    Derived d;    Base *pb = &d;    Derived *pd = &d;    // Good : behavior depends solely on type of the object      pb->fptr_arg(3.14f);   // void Base::fptr_arg(int i = 3)    pd->fptr_arg(3.14f);   // void Derived::fptr_arg(int i = 3)    pb->fptr_arg(3);   // void Base::fptr_arg(int i = 3)    pd->fptr_arg(3);   // void Derived::fptr_arg(int i = 3)        printf("\n");    // Bad : behavior depends on type of the pointer      pb->fptr_arg2(3.14f);   // void Base::fptr_arg2(int i = 3)    pd->fptr_arg2(3.14f);   // void Derived::fptr_arg2(float f = 3.140000)    pb->fptr_arg2(3);        // void Base::fptr_arg2(int i = 3)    pd->fptr_arg2(3);        // void Derived::fptr_arg2(float f = 3.000000)    printf("\n");    // Bad : behavior depends on type of the pointer      pb->vfptr_arg(3.14f);   // virtual void Derived::vfptr_arg(int i = 3)    pd->vfptr_arg(3.14f);   // virtual void Derived::vfptr_arg(int i = 3)    pb->vfptr_arg(3);   // virtual void Derived::vfptr_arg(int i = 3)    pd->vfptr_arg(3);   // virtual void Derived::vfptr_arg(int i = 3)    printf("\n");    //     pb->vfptr_arg2(3.14f);   // virtual void Base::vfptr_arg2(int i = 3)    pd->vfptr_arg2(3.14f);   // virtual void Derived::vfptr_arg2(float f = 3.140000)    pb->vfptr_arg2(3);         // virtual void Base::vfptr_arg2(int i = 3)    pd->vfptr_arg2(3);         // virtual void Derived::vfptr_arg2(float f = 3.000000)    pd->vfptr_arg3(3);         // 未被派生类隐藏    getchar();    return 0;}

 

 

反汇编代码