首页 > 编程语言 >定义模板,同时将类定义与类实现分离(C++,以栈为例)

定义模板,同时将类定义与类实现分离(C++,以栈为例)

时间:2024-10-13 15:47:35浏览次数:16  
标签:定义 temp 为例 pTop 将类 SNode next pStack Stack

一 问题背景:

        在以往单独实现树或栈时,只需要在开始使用typedef定义ElemType,后文便不必再考虑数据类型.

        但是,在实现二叉树非递归遍历时,需要借助额外的栈,树内数据类型为ElemType,但是栈内的数据类型为树节点,或者说指向树的指针,c++自带<stack>库,可以通过下列代码实现:

#include<iostream>
#include<stack>
using namespace std;
typedef int ElemType;
typedef struct TNode{
    ElemType data;
    TNode *lchild,*rchild;
}TNode,*BiTree;//定义树节点

void NLEnoRecursion(BiTree T){
    stack<BiTree> S;//使用stack库生成栈

        我们可以看到,<stack>库在生成栈时就用到了模板的知识.在定义Class类时,可以先不指定元素的数据类型,或者说可以用T来代替数据类型:

template <typename T>
typedef struct SNode{
        T data;
        struct SNode* next;
    }SNode,*pStack;

        使用<stack>库很方便快捷,并且已经足够解决遍历树的问题.但是为了更深入地学习,下面我们尝试自己编写stack模板.但是在单个文件内同时实现树与栈各种定义会很杂,而且很不好维护,所以我们考虑编写Stack类,并将类定义与实现分离.

二 Stack类的编写(不使用模板)

        为防止混淆,我们先不管模板,先把类定义搞清楚.

        class可以将类定义与类实现分离.需要注意的是,我们先将元素类型T用int来表示,待调试无误之后再扩展为模板,以下为代码,需要注意的地方都写在注释里:

#include<iostream>
using namespace std;

//template <typename T>
typedef int T;
typedef struct SNode{
        T data;
        struct SNode* next;
    }SNode,*pStack;


class Stack{
public:
    pStack pTop= new SNode;;//SNnode是我们自己创建的新数据类型,与int,float地位一致
    Stack();
    /*使用Stack()为无参构造函数,用于初始化数据域
    构造函数名字必须与类名相同,构造函数前面不需要void等返回类型
    下方Stack(pStack)同样为构造函数,用pStack将Stack初始化,即当输入一个栈时,S即指向该栈.
    */
    Stack(pStack);
    bool empty();
    bool push(T);
    bool pop();
    int length();
    T top();
};

//类可以将定义与实现分离,以上class定义类,以下代码实现class的各种操作
Stack::Stack(){
    pTop->next = NULL;
}
Stack::Stack(pStack NewStack){
    pTop = NewStack;
}
//这里用带头节点的链表来定义栈,故第一个元素为S->next,为NULL则栈空,pop失败
bool Stack::empty(){
    if (pTop->next == NULL)return true;
    else return false;
}
bool Stack::push(T n){
    SNode* temp = new SNode;
    temp->data = n;
    temp->next = pTop->next;
    pTop->next = temp;
    return true;
}
bool Stack::pop(){
    if(pTop->next == NULL){
        return false;
    }
    SNode* temp = new SNode;
    temp = pTop->next;
    pTop = temp;
    free(temp);
    return true;
}
T Stack::top(){
    T temp;
    temp = pTop->next->data;
    return temp;
}


//template <typename T>
int main(){
    Stack S;
    S.push(114);
    cout << S.pTop->next->data <<endl;
    S.top();
    cout << S.pTop->next->data <<endl;
    S.pop();
    cout << S.pTop->next->data <<endl;
    return 0;
}

三 Stack类的编写(使用模板)

参考链接:https://www.cnblogs.com/0-lingdu/p/12269554.html

        需要更改的地方不多,

1.将开头typedef int T一句移去,在class前添加template <typename T>,T即为未定义的数据类型.注意不加分号.

由于SNode的定义也用到了T,所以我们把该定义也移到class内(这里我存疑,在class内定义typedef我不确定会不会出什么问题,但至少代码不会报错):

template<typename T>
class Stack{
public:
    typedef struct SNode{
            T data;
            struct SNode* next;
        }SNode,*pStack;
    pStack pTop= new SNode;;//SNnode是我们自己创建的新数据类型,与int,float地位一致
    Stack();
    /*使用Stack()为无参构造函数,用于初始化数据域
    构造函数名字必须与类名相同,构造函数前面不需要void等返回类型
    下方Stack(pStack)同样为构造函数,用pStack将Stack初始化,即当输入一个栈时,S即指向该栈.
    */
    Stack(pStack);
    bool empty();
    bool push(T);
    bool pop();
    int length();
    T top();
};

2.在类实现每一句前面都要加template <typename T>,随后在Stack::的::加上<T>,注意是每一句

Stack<T>::Stack(pStack NewStack){
    pTop = NewStack;
}
//这里用带头节点的链表来定义栈,故第一个元素为S->next,为NULL则栈空,pop失败

template <typename T>
bool Stack<T>::empty(){
    if (pTop->next == NULL)return true;
    else return false;
}

至此完成,可以运行下列main函数:

int main(){
    Stack<int> S;
    S.push(114);
    cout << S.pTop->next->data <<endl;
    S.top();
    cout << S.pTop->next->data <<endl;
    S.pop();
    cout << S.pTop->next->data <<endl;
    return 0;
}

        第二行Stack<int>中,"int"可换为任意数据类型,可以回到这偏偏文章开头,我们编写的Stack函数与c++<stack>库使用方法完全相同.本文主要内容到此为止.更进一步,可以将Stack.h头文件与Stack.cpp文件拆开,以供其它文件调用,那些难度不大,也不方便在一篇文章内说明,这里就不展开.

        本人还在学习C++,难免有错误或疏漏,各位佬轻喷(狗头保命)

        感谢阅读,以下是完整代码.

//参考链接:https://www.cnblogs.com/0-lingdu/p/12269554.html
#include<iostream>
using namespace std;

template<typename T>
class Stack{
public:
    typedef struct SNode{
            T data;
            struct SNode* next;
        }SNode,*pStack;
    pStack pTop= new SNode;;//SNnode是我们自己创建的新数据类型,与int,float地位一致
    Stack();
    /*使用Stack()为无参构造函数,用于初始化数据域
    构造函数名字必须与类名相同,构造函数前面不需要void等返回类型
    下方Stack(pStack)同样为构造函数,用pStack将Stack初始化,即当输入一个栈时,S即指向该栈.
    */
    Stack(pStack);
    bool empty();
    bool push(T);
    bool pop();
    int length();
    T top();
};

//类可以将定义与实现分离,以上class定义类,以下代码实现class的各种操作
template <typename T>
Stack<T>::Stack(){
    pTop->next = NULL;
}

template <typename T>
Stack<T>::Stack(pStack NewStack){
    pTop = NewStack;
}
//这里用带头节点的链表来定义栈,故第一个元素为S->next,为NULL则栈空,pop失败

template <typename T>
bool Stack<T>::empty(){
    if (pTop->next == NULL)return true;
    else return false;
}

template <typename T>
bool Stack<T>::push(T n){
    SNode* temp = new SNode;
    temp->data = n;
    temp->next = pTop->next;
    pTop->next = temp;
    return true;
}

template <typename T>
bool Stack<T>::pop(){
    if(pTop->next == NULL){
        return false;
    }
    SNode* temp = new SNode;
    temp = pTop->next;
    pTop = temp;
    free(temp);
    return true;
}

template <typename T>
T Stack<T>::top(){
    T temp;
    temp = pTop->next->data;
    return temp;
}


//template <typename T>
int main(){
    Stack<int> S;
    S.push(114);
    cout << S.pTop->next->data <<endl;
    S.top();
    cout << S.pTop->next->data <<endl;
    S.pop();
    cout << S.pTop->next->data <<endl;
    return 0;
}

标签:定义,temp,为例,pTop,将类,SNode,next,pStack,Stack
From: https://blog.csdn.net/choochah/article/details/142898441

相关文章

  • Qt自定义一个圆角对话框
    如何得到一个圆角对话框?步骤:1、继承自QDiaglog2、去掉系统自带的边框3、设置背景透明,不设置4个角会有多余的部分出现颜色4、对话框内部添加1个QWidget,给这个widget设置圆角,并添加到布局中让他充满对话框5、后续对话框的所有内容都添加在这个widget里面举例:#ifndefRO......
  • 实验项目3 自定义路由转换器
    实验目的了解Django处理HTTP请求的流程。掌握路由转换器的用法。掌握如何定义和使用自定义路由转换器。实验内容操作1 创建Django项目chapter02(先进入之前创建的虚拟环境(python3.7、有Django))操作2 在项目chapter02中创建应用app01(应用需要激活应用并分配根路由、创建子......
  • 了解如何实现自定义View
    在Android开发中,自定义View是实现独特UI组件的重要手段。通过自定义View,开发者可以创建出满足特定需求、具有独特外观和行为的UI元素。以下将详细介绍如何实现自定义View,包括基础步骤、关键要点以及最佳实践。一、自定义View的基础步骤1.继承View或其子类首先,你需要创建一......