第一个C++类程序——栈
收获如下:
1.弄清楚了C++中类应该被分拆成两个文件,.h和.cpp文件;
其中h存放类的壳、函数原型,cpp中放函数定义和#include,且只在cpp中#include,否则容易出现重定义。
2.构造、析构函数的隐式和显式调用。
3.临时变量与new变量的区别:临时变量在栈中,函数运行结束自动弹出销毁,new变量在堆中,函数结束仍保留,所以用于函数内部数据返回,但用完注意delete。
4.delete指针后,指针设为nullptr。
5.k+c是注释,k+u是取注,k+f是自动缩进。
6.异常捕获。
7.cpp中函数body需要用类名::的方式定义。
问题如下:
1.尚不清楚命名空间的建立方法。
2.断点调试过程中,delete old指针后,old指针仍然指向的地方仍有数据。
3.debug窗口中看不到临时变量,只有new出来的变量和this变量。
文件MyStack.h
struct Node
{
int val;
Node *p_next;
Node *p_pre;
};
class MyStack
{
private:
Node *top;
Node *old;//pop保存老栈顶指针,用于delete
Node *pHead;
int _global;
int mySize;
public:
int size();
int isempty();
int push_back(int val);//压入
int pop();
MyStack();//半构造,因为有一部分放在push_back了
~MyStack();
};
MyStack.cpp
#include "MyStack.h"
#include<iostream>
using namespace std;
int MyStack::size()
{
return mySize;
}
int MyStack::isempty()
{
if (mySize==0){return 1;}else{return 0;}
}
int MyStack::push_back(int val)//压入
{
if(top!=nullptr)
{
Node *newNode=new Node;
newNode->p_pre=top;//新节点的pre指针指向之前的栈顶
newNode->p_next=nullptr;
newNode->val=val;
top->p_next=newNode;//老栈顶的next指针指向新节点
top=newNode;//top指针改为新节点地址
}
else//若第一次初始化
{
pHead=new Node; //实例结构体
pHead->p_pre=nullptr;
pHead->p_next=nullptr;
pHead->val=val;
top=pHead;
}
mySize++;
return 0;
}
int MyStack::pop()
{
try{
if(top==nullptr)
{
throw("stack is null"); //测试抛出异常
}
_global=top->val;
old=top;
top=top->p_pre;//问题1,该位置没有变化,直到执行下句delete old才有变化
delete old;//问题2,该位置没有变化,释放完后old还是指向有数据的空间
old=nullptr;
mySize--;//问题3,在这里int a=0;并不出现a的变量信息
if(mySize==0){pHead=nullptr;top=nullptr;}
return _global;
}catch(const char* msg)
{
cout<<msg<<endl;
return -1;
};
}
MyStack::MyStack()//半构造,因为有一部分放在push_back了
{
top=nullptr;
old=nullptr;
_global=NULL;
pHead=nullptr;
mySize=0;//********************************
cout<<"构造完成"<<endl;
}
MyStack::~MyStack()
{
if (pHead!=nullptr)
{
Node *tmp1;
Node *tmp2;
tmp1=pHead->p_next;
while(tmp1!=nullptr)//循环释放
{
tmp2=tmp1;
tmp1=tmp2->p_next;
delete tmp2;
tmp2=nullptr;
};
tmp1=nullptr;
tmp2=nullptr;
delete pHead;
pHead=nullptr;//释放完空间后指针设为nullptr
_global=NULL;
}
cout<<"析构完成"<<endl;
}
main.cpp
#include"MyStack.h"
#include<iostream>
using namespace std;
int main(){
MyStack stack;//这里不是new出来的,所以在栈空间,当main结束后自动析构(隐式)
MyStack *newStack=new MyStack;
newStack->~MyStack();//这里是new出来的,在堆空间,main结束后不会析构,需要显式调用
cout<<"当前个数:"<<stack.size()<<endl;
cout<<"空时返回1:"<<stack.isempty()<<endl;
stack.push_back(1);
stack.push_back(2);
cout<<"当前个数:"<<stack.size()<<endl;
cout<<stack.pop()<<endl;
cout<<stack.pop()<<endl;
stack.push_back(3);
cout<<stack.pop()<<endl;
cout<<stack.pop()<<endl;//测试异常处理
return 0;
}
运行结果为:隐式、显式分别调用一次构造析构函数。