跟着动手,泛型编程从未如此简单2

跟着动手,知行泛型编程

实现一个”泛型”的Stack

接着上一篇内容继续,上一篇中实现了一个支持int类型的Stack,接下来将实现一个支持泛型的Stack,我们先假设要现在一个支持内置类型的Stack,如:int, float, double, short等。

  • 让我们先从头文件的定义开始,直接上代码:GenericStack.h
#include <iostream>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

class GenericStack{
    public:
        int m_nLogicLen;                     //栈的实际长度
        int m_nAssignLen;                    //栈分配的空间的长度
        void* m_pElementBuffer;              //栈中数据的存放空间地址
        int m_nElementSize;                  //新增加的参数,栈中保存的数据的字节长度,如int:4
    public:
        GenericStack(int elementSize);      
        ~GenericStack();
    public:
        bool GenericStackPush(void* elementBuffer);    //入栈
        bool GenericStackPop(void* elementBuffer);     //出栈
    private:
        bool GenericStackGrow();
};
  • GenericStack.cpp实现:
/*
* @brief 构造函数
* @elementSize 栈中存放的元素的字节长度
*/
GenericStack::GenericStack(int elementSize){
    this->m_nLogicLen = 0;
    this->m_nAssignLen = 4;
    this->m_nElementSize = elementSize;
    this->m_pElementBuffer = malloc(this->m_nAssignLen * this->m_nElementSize);
    assert(this->m_pElementBuffer != NULL);
}
/*
* @brief 析构函数
*/
GenericStack::~GenericStack(){
    free(this->m_pElementBuffer);
}
/*
* @brief 入栈
* @elementBuffer 入栈元素的地址
*/
bool GenericStack::GenericStackPush(void* elementBuffer){
    if( this->m_nLogicLen == this->m_nAssignLen){
        GenericStackGrow();
    } 
    void* target = (char*)this->m_pElementBuffer + this->m_nLogicLen * this->m_nElementSize;
    memcpy(target, elementBuffer, this->m_nElementSize);
    this->m_nLogicLen ++;
    return true;
}
/*
* @brief 出栈
* @elementBuffer 出栈元素的地址
*/
bool GenericStack::GenericStackPop(void* elementBuffer){
    void* target = (char*)this->m_pElementBuffer + (this->m_nLogicLen - 1) * this->m_nElementSize;
    memcpy(elementBuffer, target, this->m_nElementSize);
    this->m_nLogicLen --;
    return true;
}
/*
* @brief 栈元素空间增长
*/
bool GenericStack::GenericStackGrow(){
    assert(this->m_nAssignLen > 0);
    this->m_nAssignLen  = this->m_nAssignLen * 2;
    this->m_pElementBuffer = realloc(this->m_pElementBuffer, this->m_nAssignLen * this->m_nElementSize );
    assert( this->m_pElementBuffer != NULL);
    return true;
}

现在一个支持内置类型的“泛型”Stack就算实现好了,相比较与上一章所介绍的Stack,支持类更多的内置类型

知识点

  • void*指针不可以直接进行+/-,取值等运算,必须要转化为相应的类型指针,比如char*

这样一个简单的“泛型”,就算完成了,可是对于自定义的数据类型,该Stack明显显的心有余而力不足,我来举个例子:

    char* stringNames[] = {"ali","bob","peter"};
    //push
    for(int i = 0; i < 3; i++){
        char* copy = strdup(stringNames[i]);//strdup内部会调用malloc开辟内存,需要调用free
        stackObj.GenericStackPush(&copy);
    }
    //pop
    char* name;
    for(int i = 0; i < 3; i++){//以上使用了malloc这里要对应free
        stackObj.GenericStackPop(&name);
        printf("pop: %s\n",name);
        free(name);
    }

对于上述例子,入栈的数据本身进行了内存开辟,入栈3个数据,出栈3个数据,没有问题,但是当我们的pop出栈部分改成如下代码时:

    //pop
    char* name;
    for(int i = 0; i < 1; i++){//出栈一次,只释放类最后一个数据开辟的内存空间
        stackObj.GenericStackPop(&name);
        printf("pop: %s\n",name);
        free(name);
    }

很明显上述代码就会存在内存泄漏问题,如何解决该问题?

关键点:

  • 如何自定义专属数据类型的“析构函数”?

带着这个问题,接下来我将实现一个正真意义上的泛型Stack
推荐一首歌,还是一首嘻哈曲风的歌曲,安全着陆我欲乘风……..

border="0" width="330" height="86" src="//music.163.com/outchain/player?type=2&id=454953939&auto=1&height=66">
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值