C++98corebeginner
Nested Classes
C++98 · The Foundation · Compiler flag: -std=c++98
Explanation
A class defined inside the scope of another class, typically used as an implementation detail.
Real-World Scenario
A `LinkedList` class containing a private `Node` class that only it needs.
Quick Snippet
snippet.cpp
class List { class Node { int data; Node* next; }; };Full Example
nested_classes.cpp
// CodeNebula - C++98 Example: Nested Classes
// Compile: g++ -std=c++98 -Wall -Wextra -o example nested_classes.cpp
//
// This example demonstrates:
// - Defining a class inside another class
// - Access rules: nested class CAN access outer class's members (with object)
// - Outer class can access nested class's private members (in C++98, this
// depends on the compiler; the standard made it official in C++11, but most
// C++98 compilers allow it when the nested class is in scope)
// - Nested classes for encapsulation: hiding implementation details
// - Practical use: Node inside a container, State inside a state machine
#include <iostream>
#include <cstring>
// ============================================================
// 1. Basic nested class
// ============================================================
class Outer {
private:
int outerData;
public:
Outer(int v) : outerData(v) {}
// Nested class defined INSIDE Outer
class Inner {
private:
int innerData;
public:
Inner(int v) : innerData(v) {}
void show() const {
std::cout << " Inner::innerData = " << innerData << std::endl;
}
// Inner can access Outer's private members IF given an Outer object
void showOuter(const Outer& o) const {
std::cout << " Accessing Outer::outerData = " << o.outerData << std::endl;
}
};
void demo() const {
Inner i(100);
i.show();
i.showOuter(*this);
}
};
// ============================================================
// 2. Practical: Stack with nested Node
// ============================================================
class Stack {
private:
// Node is an implementation detail -- hidden from users of Stack
struct Node {
int data;
Node* next;
Node(int d, Node* n) : data(d), next(n) {}
};
Node* top_;
int size_;
public:
Stack() : top_(NULL), size_(0) {}
~Stack() {
while (top_ != NULL) {
Node* temp = top_;
top_ = top_->next;
delete temp;
}
}
void push(int value) {
top_ = new Node(value, top_);
++size_;
}
int pop() {
if (top_ == NULL) {
std::cout << " ERROR: stack is empty!" << std::endl;
return -1;
}
int value = top_->data;
Node* temp = top_;
top_ = top_->next;
delete temp;
--size_;
return value;
}
int peek() const {
if (top_ == NULL) {
std::cout << " ERROR: stack is empty!" << std::endl;
return -1;
}
return top_->data;
}
bool empty() const { return top_ == NULL; }
int size() const { return size_; }
void print() const {
std::cout << " Stack [top->bottom]: ";
Node* n = top_;
while (n != NULL) {
std::cout << n->data;
if (n->next != NULL) std::cout << " -> ";
n = n->next;
}
if (top_ == NULL) std::cout << "(empty)";
std::cout << std::endl;
}
};
// ============================================================
// 3. State Machine with nested State classes
// ============================================================
class TrafficLight {
public:
// Nested: represents a traffic light state
class State {
private:
char name[16];
int durationSec;
char nextState[16];
public:
State() : durationSec(0) {
name[0] = '\0';
nextState[0] = '\0';
}
State(const char* n, int dur, const char* next) : durationSec(dur) {
std::strncpy(name, n, 15);
name[15] = '\0';
std::strncpy(nextState, next, 15);
nextState[15] = '\0';
}
const char* getName() const { return name; }
int getDuration() const { return durationSec; }
const char* getNextName() const { return nextState; }
void display() const {
std::cout << " [" << name << "] duration=" << durationSec
<< "s, next=" << nextState << std::endl;
}
};
private:
State states[3];
int currentIndex;
int findState(const char* name) const {
for (int i = 0; i < 3; ++i) {
if (std::strcmp(states[i].getName(), name) == 0) {
return i;
}
}
return -1;
}
public:
TrafficLight() : currentIndex(0) {
states[0] = State("GREEN", 30, "YELLOW");
states[1] = State("YELLOW", 5, "RED");
states[2] = State("RED", 20, "GREEN");
}
void showCurrent() const {
std::cout << " Current: ";
states[currentIndex].display();
}
void advance() {
const char* nextName = states[currentIndex].getNextName();
int nextIdx = findState(nextName);
if (nextIdx >= 0) {
currentIndex = nextIdx;
}
}
// Expose nested type for external use
State getCurrentState() const { return states[currentIndex]; }
};
// ============================================================
// 4. Nested class with public access (used externally)
// ============================================================
class Matrix {
public:
// Publicly nested: users can create Matrix::Dimensions
class Dimensions {
public:
int rows;
int cols;
Dimensions(int r, int c) : rows(r), cols(c) {}
void print() const {
std::cout << " " << rows << " x " << cols << std::endl;
}
};
private:
Dimensions dims;
double* data;
public:
Matrix(int r, int c) : dims(r, c), data(new double[r * c]) {
for (int i = 0; i < r * c; ++i) {
data[i] = 0.0;
}
}
~Matrix() { delete[] data; }
Dimensions getDimensions() const { return dims; }
void set(int r, int c, double val) {
if (r >= 0 && r < dims.rows && c >= 0 && c < dims.cols) {
data[r * dims.cols + c] = val;
}
}
double get(int r, int c) const {
if (r >= 0 && r < dims.rows && c >= 0 && c < dims.cols) {
return data[r * dims.cols + c];
}
return 0.0;
}
void print() const {
for (int r = 0; r < dims.rows; ++r) {
std::cout << " | ";
for (int c = 0; c < dims.cols; ++c) {
std::cout << get(r, c) << " ";
}
std::cout << "|" << std::endl;
}
}
};
int main() {
std::cout << "========================================" << std::endl;
std::cout << "1. BASIC NESTED CLASS" << std::endl;
std::cout << "========================================" << std::endl;
{
Outer o(42);
o.demo();
// Can also create Inner from outside using scope resolution
Outer::Inner i(200);
i.show();
i.showOuter(o);
}
std::cout << "\n========================================" << std::endl;
std::cout << "2. STACK WITH NESTED NODE (hidden implementation)" << std::endl;
std::cout << "========================================" << std::endl;
{
Stack s;
s.push(10);
s.push(20);
s.push(30);
s.print();
std::cout << " peek: " << s.peek() << std::endl;
std::cout << " pop: " << s.pop() << std::endl;
std::cout << " pop: " << s.pop() << std::endl;
s.print();
// Stack::Node n; // COMPILE ERROR: Node is private
std::cout << " Stack::Node n; // COMPILE ERROR: Node is private" << std::endl;
}
std::cout << "\n========================================" << std::endl;
std::cout << "3. TRAFFIC LIGHT STATE MACHINE" << std::endl;
std::cout << "========================================" << std::endl;
{
TrafficLight tl;
for (int cycle = 0; cycle < 6; ++cycle) {
tl.showCurrent();
tl.advance();
}
// Use the nested State type externally
TrafficLight::State st = tl.getCurrentState();
std::cout << " Final state: " << st.getName() << std::endl;
}
std::cout << "\n========================================" << std::endl;
std::cout << "4. MATRIX WITH PUBLIC NESTED DIMENSIONS" << std::endl;
std::cout << "========================================" << std::endl;
{
Matrix m(3, 3);
m.set(0, 0, 1.0);
m.set(1, 1, 2.0);
m.set(2, 2, 3.0);
std::cout << " Matrix dimensions: ";
Matrix::Dimensions d = m.getDimensions();
d.print();
m.print();
// Create Dimensions independently
Matrix::Dimensions custom(4, 5);
std::cout << " Custom dimensions: ";
custom.print();
}
std::cout << "\n========================================" << std::endl;
std::cout << "5. KEY POINTS" << std::endl;
std::cout << "========================================" << std::endl;
std::cout << " - Nested classes are defined inside another class" << std::endl;
std::cout << " - Access from outside: Outer::Inner (if public)" << std::endl;
std::cout << " - Private nested classes hide implementation details" << std::endl;
std::cout << " - Nested class can access outer's private members (via object)" << std::endl;
std::cout << " - Common uses: Node in containers, State in state machines," << std::endl;
std::cout << " Iterator in collections, Impl in Pimpl pattern" << std::endl;
return 0;
}
// Expected output:
// ========================================
// 1. BASIC NESTED CLASS
// ========================================
// Inner::innerData = 100
// Accessing Outer::outerData = 42
// Inner::innerData = 200
// Accessing Outer::outerData = 42
//
// ========================================
// 2. STACK WITH NESTED NODE
// ========================================
// Stack [top->bottom]: 30 -> 20 -> 10
// peek: 30
// pop: 30
// pop: 20
// Stack [top->bottom]: 10
// Stack::Node n; // COMPILE ERROR: Node is private
//
// ========================================
// 3. TRAFFIC LIGHT STATE MACHINE
// ========================================
// Current: [GREEN] duration=30s, next=YELLOW
// Current: [YELLOW] duration=5s, next=RED
// Current: [RED] duration=20s, next=GREEN
// Current: [GREEN] duration=30s, next=YELLOW
// Current: [YELLOW] duration=5s, next=RED
// Current: [RED] duration=20s, next=GREEN
// Final state: GREEN
//
// ========================================
// 4. MATRIX WITH PUBLIC NESTED DIMENSIONS
// ========================================
// Matrix dimensions: 3 x 3
// | 1 0 0 |
// | 0 2 0 |
// | 0 0 3 |
// Custom dimensions: 4 x 5
Run command
g++ -std=c++98 -Wall -Wextra -o example nested_classes.cpp