// Definition of a Node for the linked-list used by the Stack internally
// To allow 'Stack' class to access private members of 'Node' class
// Parameterized constructor member initialization
Node(const int val) : data(val), next(nullptr) {}
Node *top; // Points to topmost element in stack
size_t size; // Denotes number of elements in queue
// Default constructor member initialization
Stack() : top(nullptr), size(0) {}
// Check if stack is empty (doesn't modify state)
// Stack is empty when top is not pointing to anything
// Returns number of elements present in stack (doesn't modify state)
const size_t getSize() { return size; }
// Insert an element on top of stack
// Allocate memory for the new element
Node *newNode = new Node(val);
// The new node must point to previously topmost item in stack
// The updated top of stack is the new node
size++; // Increment size after insertion
// Get the topmost element in stack (doesn't modify state)
throw underflow_error("Cannot access top element in empty stack");
// Remove the topmost element from stack
throw underflow_error("Cannot pop element from empty stack");
Node *nodeToDelete = top; // Store the topmost node's address
top = nodeToDelete->next; // Make top point to the second topmost
delete nodeToDelete; // Deallocate the top node's memory
size--; // Decrement size after deletion
// Destructor to deallocate memory of all items of stack
// Keep popping items till stack isn't empty
// Create an instance of our 'Stack' class
cout << "Size: " << stk.getSize() << endl;
Access/Delete operations on empty stack will throw underflow exception and exit:
cout << stk.peek() << endl;
// UNDERFLOW: Cannot access top element in empty stack
// UNDERFLOW: Cannot pop element from empty stack
stk.push(15); stk.push(48);
stk.push(23); stk.push(37);
cout << "Size: " << stk.getSize() << ", Top: " << stk.peek() << endl;
cout << "Size: " << stk.getSize() << ", Top: " << stk.peek() << endl;
catch (underflow_error const &ue) {
cout << "UNDERFLOW: " << ue.what() << endl;
catch (overflow_error const &oe) {
cout << "OVERFLOW: " << oe.what() << endl;
catch (exception const &e) {
cout << "Other exception: " << e.what() << endl;