Nested Class (คลาสซ้อน) คือ คลาสที่ประกาศ ภายในคลาสอื่น เรียกคลาสภายนอกว่า Enclosing Class
ลักษณะสำคัญ
- เป็น Member ของ Enclosing Class (เหมือน Variable/Function)
- มี Access Specifier ของตัวเอง (public/private/protected)
- Enclosing Class ไม่มีสิทธิ์พิเศษ เข้าถึง private ของ Nested Class
- Nested Class ไม่มีสิทธิ์พิเศษ เข้าถึง private ของ Enclosing Class
- Scope:
Enclosing::Nested
โค้ดตัวอย่างพื้นฐาน
#include <iostream>
using namespace std;
class Outer {
public:
class Inner {
private:
int num;
public:
void setData(int n) { num = n; }
void showData() { cout << "Number: " << num << endl; }
};
};
int main() {
Outer::Inner obj; // Scope resolution
obj.setData(9);
obj.showData();
return 0;
}
ผลลัพธ์
Number: 9
การเข้าถึงสมาชิก (Access Rules)
class Outer {
private:
int outerPrivate = 10;
static int outerStatic;
public:
class Inner {
public:
void accessOuter(Outer& o) {
// cout << o.outerPrivate; // ❌ Error: ไม่เข้าถึง private ได้
cout << Outer::outerStatic; // ✓ static member OK
}
};
void accessInner(Inner& i) {
// cout << i.num; // ❌ Error: ไม่เข้าถึง private ของ Inner ได้
}
};
int Outer::outerStatic = 42;
Static Nested Class (C++ ไม่มี static class แต่นิยมเรียกแบบนี้)
ถ้า Nested Class ไม่ต้องการเข้าถึง Non-static Member ของ Outer ให้ทำเป็น ไม่ผูกกับ Instance
class Outer {
public:
class Nested {
public:
static void utility() { cout << "Utility" << endl; }
};
};
int main() {
Outer::Nested::utility(); // เรียกได้โดยไม่ต้องมี Outer Object
}
การใช้งานจริง: Iterator Pattern
#include <iostream>
#include <vector>
using namespace std;
class Container {
vector<int> data;
public:
void add(int v) { data.push_back(v); }
// Nested Iterator Class
class Iterator {
const vector<int>& vec;
size_t index;
public:
Iterator(const vector<int>& v, size_t idx) : vec(v), index(idx) {}
int operator*() const { return vec[index]; }
Iterator& operator++() { ++index; return *this; }
bool operator!=(const Iterator& other) const { return index != other.index; }
};
Iterator begin() const { return Iterator(data, 0); }
Iterator end() const { return Iterator(data, data.size()); }
};
int main() {
Container c;
c.add(10); c.add(20); c.add(30);
for (auto it = c.begin(); it != c.end(); ++it)
cout << *it << " "; // 10 20 30
// Range-based for ก็ได้ (ถ้ามี begin/end)
for (int x : c) cout << x << " ";
}
การใช้งานจริง: Node ใน Linked List/Tree
class LinkedList {
private:
struct Node { // struct = public by default
int data;
Node* next;
Node(int d) : data(d), next(nullptr) {}
};
Node* head = nullptr;
public:
void push_front(int val) {
Node* n = new Node(val);
n->next = head;
head = n;
}
// Nested Class สำหรับ Iterator
class Iterator {
Node* current;
public:
Iterator(Node* n) : current(n) {}
int operator*() { return current->data; }
Iterator& operator++() { current = current->next; return *this; }
bool operator!=(const Iterator& other) { return current != other.current; }
};
Iterator begin() { return Iterator(head); }
Iterator end() { return Iterator(nullptr); }
};
ข้อดีและข้อเสีย
| ข้อดี | ข้อเสีย |
|---|---|
| จัดกลุ่ม Logic ที่เกี่ยวข้อง (Encapsulation) | เพิ่ม Complexity ของ Class ภายนอก |
| ควบคุม Visibility (private nested class) | Syntax ยุ่งยาก (Outer::Inner::Member) |
| เข้าถึง Static Members ของ Outer ได้ | ไม่เข้าถึง Non-static Members ของ Outer ได้โดยตรง |
| ใช้สร้าง Iterator, Traits, Policies | Compile time นานขึ้นเล็กน้อย |
Local Class (คลาสในฟังก์ชัน) - เปรียบเทียบ
void func() {
class LocalClass { // Local to this function
int x;
public:
void set(int v) { x = v; }
};
LocalClass obj; // ใช้ได้เฉพาะใน func()
obj.set(10);
}
// LocalClass ไม่เข้าถึงได้นอก func()
Local Class: จำกัด Scope ใน Function | Nested Class: จำกัด Scope ใน Class