First , a few general comments that in this case do not cause problems, but some can do this in other situations:
You should only throw exceptions derived from the class std::exception. C ++ allows you to throw any type (e.g. a string in your case), but this is a really bad idea.
, : ( . , , , . -, , )
Node(int val, Node* ptrToLast) : value(val), prev(ptrToLast) {}
Stack() : size(0), top(NULL) {}
return* . size() topPtr(), , , getSize() getTopPtr()
, .;)
-, .:)
, , :
, :
void test() {
Stack s;
s.peek();
}
, node ( ):
void test() {
Stack s;
s.push(1);
}
:
~Stack() {
while (top != NULL){
Node* next = top.returnPtr();
delete top;
top = next;
}
}
:
void test() {
Stack s;
s.push(1);
Stack t(s);
s.pop();
}
t.returnSize() 1, t.top node s, . (, , node)
:
Stack(const Stack& s);
, , .
:
Stack& operator= (const Stack& s);
, , :
Stack s;
Stack t;
t = s;
, , t s. node s t, . ( , , Stack. , , , )
, , :
void test() {
Stack s;
s.push(1);
s.push(2);
}
, node (, . , ). , . s 2, top node
, , , . , , , int.
, , node, . . , , .
" " . , , ? ? ( ). - ( , ), , ? , ? ( , )
- , . , . sometihng , , ++.:)
Bonus:
, , RAII, :
-, , , , , .
-, , , . . ( , getSize): ( live - , . Stack, , , , . , Stack, , .
static int live; // debugging - keeps track of how many nodes have been allocated. Constructors add 1, destructors subtract. It should end in 0
int main(){
{
// test stack creation + push
Stack s;
s.push(1);
s.push(2);
s.push(3);
assert(s.getSize() == 3);
Stack t;
t.push(4);
t.push(5);
t.push(6);
assert(t.getSize() == 3);
// test assigment operator when both stacks contain data
s = t;
assert(s.getSize() == 3);
assert(s.peek() == 6);
assert(t.peek() == 6);
Stack u(s);
// test self assigment when stack contains data
u = u;
assert(u.getSize() == 3);
assert(u.peek() == 6);
Stack v;
// test copy construction from stack with data
Stack w(t);
assert(w.getSize() == 3);
assert(w.peek() == 6);
assert(t.getSize() == 3);
assert(t.peek() == 6);
// test assignment operator when source is empty, destination contains data
w = v;
assert(w.getSize() == 0);
assert(v.getSize() == 0);
// test copy construction from empty stack
Stack x(v);
assert(x.getSize() == 0);
assert(v.getSize() == 0);
// test pop
assert(t.pop() == 6);
assert(t.pop() == 5);
assert(t.pop() == 4);
assert(s.pop() == 6);
assert(s.pop() == 5);
assert(s.pop() == 4);
} // at this point, all allocated stacks go out of scope, so their destructors are called, so now is a good time to check for memory leaks:
assert(live == 0);
}
, . , Stack. node - , , , , , . , Stack Node.tail_, , . , .
#include <stdexcept> // for std::exception
class Stack;
class Node
{
private:
int head_;
Node* tail_;
public:
friend class Stack;
int head() const { return head_; }
Node* tail() const { return tail_; }
Node(int val, Node* prev) : head_(val), tail_(prev) { ++live; }
~Node() { --live; }
Node(const Node& other) : head_(other.head_), tail_(other.tail_){ ++live; };
};
class Stack
{
private:
Node* top;
bool empty() const { return top == NULL;}
void freeNodes() {
while (!empty()){
pop();
}
}
public:
Stack() : top() {}
~Stack() {
freeNodes();
}
Stack(const Stack& other) : top() {
if (other.empty()){
return;
}
top = new Node(*other.top);
Node* otherNext = other.top->tail();
Node* current = top;
while (otherNext != NULL){
current->tail_ = new Node(*otherNext);
current = current->tail();
otherNext = otherNext->tail();
}
}
Stack& operator= (const Stack& other) {
if (this == &other){
return *this;
}
try {
if (other.empty()){
freeNodes();
top = NULL;
return *this;
}
Node* newTop = new Node(*other.top);
Node* otherNext = other.top->tail();
Node* current = newTop;
while (otherNext != NULL){
current->tail_ = new Node(*otherNext);
current = current->tail();
otherNext = otherNext->tail();
}
freeNodes();
top = newTop;
return *this;
}
catch (...){
throw;
}
}
void push(int);
int pop();
int peek() const;
int getSize() const{
if (empty()){ return 0; }
int i = 0;
for (Node* cur = top; cur != NULL; cur = cur->tail_, ++i){}
return i;
}
};
void Stack::push(int value)
{
Node* currentTop = top;
top = new Node(value, currentTop);
}
int Stack::peek() const
{
if (empty()){
throw std::exception("Stack is empty");
}
return top->head();
}
int Stack::pop()
{
if (empty()){
throw std::exception("Stack is empty");
}
Node* tail = top->tail();
int result = top->head();
delete top;
top = tail;
return result;
}
RAII v. 1
RAII - . , (, , new.) , .
, Stack , , Node. Node , . top node... . , Stack.push , Node ., , , node.
Stack still needs to access the tail_ member of Node `, accessor , . , , .
#include <stdexcept>
class Node
{
private:
int head_;
Node* tail_;
public:
int head() const { return head_; }
Node* tail() const { return tail_; }
Node*& tail() { return tail_; }
Node(int val, Node* prev = NULL) : head_(val), tail_(prev) { ++live; }
~Node(){ --live; delete tail_; }
Node(const Node& other) : head_(other.head()), tail_(NULL) {
++live;
if (other.tail() == NULL){
return;
}
tail_ = new Node(*other.tail());
}
Node& operator= (const Node& other){
if (this == &other){
return *this;
}
head_ = other.head();
if (other.tail() != NULL){
return *this;
}
Node* oldTail = tail_;
try {
tail_ = new Node(*other.tail());
}
catch(...){
tail_ = oldTail;
throw;
}
}
};
class Stack
{
private:
Node* top;
bool empty() const { return top == NULL;}
public:
Stack() : top() {}
~Stack() {
delete top;
}
Stack(const Stack& other) : top(){
if (other.empty()){
return;
}
top = new Node(*other.top);
}
Stack& operator= (const Stack& other) {
if (this == &other){
return *this;
}
Node* oldTop = top;
try {
top = NULL;
if (other.top != NULL){
top = new Node(*other.top);
}
delete oldTop;
return *this;
}
catch (...){
delete top;
top = oldTop;
throw;
}
}
void push(int);
int pop();
int peek() const;
int getSize() const{
if (empty()){ return 0; }
int i = 0;
for (Node* cur = top; cur != NULL; cur = cur->tail(), ++i){}
return i;
}
};
void Stack::push(int value)
{
Node* currentTop = top;
top = new Node(value, currentTop);
}
int Stack::peek() const
{
if (empty()){
throw std::exception("Stack is empty");
}
return top->head();
}
int Stack::pop()
{
if (empty()){
throw std::exception("Stack is empty");
}
Node* tail = top->tail();
int result = top->head();
if (top != NULL){
top->tail() = NULL;
delete top;
}
top = tail;
return result;
}
RAII v.2
, , . Node , push/pop/peek. Stack - . . Stack Node, . node, - node , , node. .
, isLast node, Stack.pop , top. 100% ( , )
, , . ( , , .;))
#include <stdexcept>
class Node {
public:
Node(int value, Node* prev = 0) : head(value), tail(prev) { ++live;}
~Node() {
--live;
delete tail;
}
Node(const Node& other) : head(other.head), tail(0) {
++live;
if (other.tail != 0){
tail = new Node(*other.tail);
}
}
Node& operator= (const Node& other){
if (this == &other){
return *this;
}
Node* oldTail = tail;
tail = new Node(*other.tail);
delete oldTail;
head = other.head;
return *this;
}
void push(int val){
tail = new Node(head, tail);
head = val;
}
int peek(){
return head;
}
void pop(){
Node* oldTail = tail;
head = tail->head;
tail = tail->tail;
oldTail->tail = 0;
delete oldTail;
}
bool isLast() { return tail == NULL; }
int getSize() const{
int i = 0;
for (const Node* cur = this; cur != NULL; cur = cur->tail, ++i){}
return i;
}
private:
Node* tail;
int head;
};
class Stack {
public:
Stack() : top(){}
~Stack() { delete top; }
Stack(const Stack& other) : top() {
if (other.empty()){
return;
}
top = new Node(*other.top);
}
Stack& operator= (const Stack& other){
if (this == &other){
return *this;
}
Node* newTop = NULL;
if (!other.empty()){
newTop = new Node(*other.top);
}
delete top;
top = newTop;
return *this;
}
void push(int val){
if (empty()) {
top = new Node(val);
}
else {
top->push(val);
}
}
int peek(){
if (empty()){
throw std::exception("Empty stack");
}
return top->peek();
}
int pop(){
int result = peek();
if (top->isLast()){
delete top;
top = NULL;
}
else {
top->pop();
}
return result;
}
int getSize() const{
if (empty()){ return 0; }
return top->getSize();
}
private:
bool empty() const { return top == NULL; }
Node* top;
};
, ++ - , , !
:)