系列: C++
cpp
267 行
· 更新于 2026-04-03
constructors.cpp
C++/Part2_物件導向/Ch09_建構子與解構子/constructors.cpp
// ============================================================
// Ch09 — 建構子完整範例
// 預設、帶參數、多載、初始化列表、委託建構子、
// explicit、= default / = delete
// 編譯:g++ -std=c++17 -Wall -o constructors constructors.cpp
// ============================================================
#include <iostream>
#include <string>
// ============================================================
// 1. Date — 多種建構子示範
// ============================================================
class Date {
private:
int year;
int month;
int day;
public:
// 完整參數建構子
Date(int year, int month, int day)
: year(year), month(month), day(day) {
std::cout << " Date(" << year << ", " << month << ", "
<< day << ") 完整建構子" << std::endl;
}
// 委託建構子 — 預設日期
Date() : Date(2000, 1, 1) {
std::cout << " → 委託自預設建構子" << std::endl;
}
// 委託建構子 — 只給年份
Date(int year) : Date(year, 1, 1) {
std::cout << " → 委託自單參數建構子" << std::endl;
}
// const 成員函式
int getYear() const { return year; }
int getMonth() const { return month; }
int getDay() const { return day; }
bool isLeapYear() const {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
void print() const {
std::cout << " " << year << "/" << month << "/" << day;
if (isLeapYear()) std::cout << "(閏年)";
std::cout << std::endl;
}
};
// ============================================================
// 2. Person — 初始化列表與 const 成員
// ============================================================
class Person {
private:
const int id; // const 成員 → 必須用初始化列表
std::string name;
int age;
public:
// 必須使用初始化列表初始化 const 成員
Person(int id, const std::string& name, int age)
: id(id), name(name), age(age) {}
// 委託建構子
Person(int id, const std::string& name)
: Person(id, name, 0) {}
void print() const {
std::cout << " [ID:" << id << "] " << name
<< ", " << age << " 歲" << std::endl;
}
int getId() const { return id; }
};
// ============================================================
// 3. Meter — explicit 關鍵字示範
// ============================================================
class Meter {
private:
double value;
public:
// 加上 explicit 防止隱式轉換
explicit Meter(double v) : value(v) {}
double getValue() const { return value; }
void print() const {
std::cout << " " << value << " 公尺" << std::endl;
}
};
// 接受 Meter 的函式 — 用於測試隱式轉換
void printDistance(const Meter& m) {
std::cout << " 距離: " << m.getValue() << " m" << std::endl;
}
// ============================================================
// 4. Counter — = default 與 = delete
// ============================================================
class Counter {
private:
int count;
public:
Counter() = default; // 明確要求預設建構子
explicit Counter(int initial) : count(initial) {}
Counter(const Counter&) = delete; // 禁止拷貝
Counter& operator=(const Counter&) = delete; // 禁止拷貝賦值
void increment() { ++count; }
void decrement() { --count; }
int getCount() const { return count; }
void print() const {
std::cout << " Counter = " << count << std::endl;
}
};
// ============================================================
// 5. InitOrder — 初始化順序示範
// ============================================================
class InitOrder {
private:
int a; // 先宣告 → 先初始化
int b; // 後宣告 → 後初始化
public:
// 初始化列表的順序應與宣告順序一致
// 如果寫成 b(val*2), a(val),編譯器會警告
InitOrder(int val) : a(val), b(a + 1) {
std::cout << " a = " << a << ", b = " << b << std::endl;
std::cout << " (初始化順序依宣告順序:先 a 再 b)" << std::endl;
std::cout << " (b 依賴 a 的值,因為 a 宣告在前所以安全)" << std::endl;
}
};
// ============================================================
// 6. Logger — 解構子示範
// ============================================================
class Logger {
private:
std::string name;
public:
Logger(const std::string& name) : name(name) {
std::cout << " [Logger] " << name << " 建構" << std::endl;
}
~Logger() {
std::cout << " [Logger] " << name << " 解構" << std::endl;
}
void log(const std::string& msg) const {
std::cout << " [" << name << "] " << msg << std::endl;
}
};
// ============================================================
// main
// ============================================================
int main() {
std::cout << "========================================" << std::endl;
std::cout << " Ch09 建構子完整範例" << std::endl;
std::cout << "========================================\n" << std::endl;
// ------ 1. Date — 多種建構子 ------
std::cout << "【1】Date — 建構子多載與委託\n" << std::endl;
Date d1; // 預設建構子 → 委託 → Date(2000,1,1)
std::cout << std::endl;
Date d2(2024); // 單參數 → 委託 → Date(2024,1,1)
std::cout << std::endl;
Date d3(2024, 3, 15); // 完整建構子
std::cout << std::endl;
std::cout << " 建立的日期:" << std::endl;
d1.print();
d2.print();
d3.print();
std::cout << std::endl;
// ------ 2. Person — const 成員與初始化列表 ------
std::cout << "【2】Person — const 成員必須用初始化列表\n" << std::endl;
Person p1(1001, "小明", 20);
Person p2(1002, "小華", 22);
Person p3(1003, "小美"); // 委託建構子,age 預設 0
p1.print();
p2.print();
p3.print();
// p1.id = 999; // 編譯錯誤!const 成員不可修改
std::cout << std::endl;
// ------ 3. Meter — explicit 示範 ------
std::cout << "【3】Meter — explicit 防止隱式轉換\n" << std::endl;
Meter m1(100.0); // ✓ 直接初始化
Meter m2{50.5}; // ✓ 大括號初始化
// Meter m3 = 30.0; // ✗ 編譯錯誤!explicit 禁止隱式轉換
m1.print();
m2.print();
printDistance(Meter(200.0)); // ✓ 顯式建構
// printDistance(200.0); // ✗ 編譯錯誤!不允許隱式轉換
std::cout << std::endl;
// ------ 4. Counter — = default / = delete ------
std::cout << "【4】Counter — = default / = delete\n" << std::endl;
Counter c1(10);
c1.increment();
c1.increment();
c1.print();
// Counter c2 = c1; // ✗ 編譯錯誤!拷貝被 delete
// Counter c3; c3 = c1; // ✗ 編譯錯誤!拷貝賦值被 delete
std::cout << " 拷貝建構子與拷貝賦值運算子已被 delete" << std::endl;
std::cout << std::endl;
// ------ 5. InitOrder — 初始化順序 ------
std::cout << "【5】初始化順序(依宣告順序,非初始化列表順序)\n" << std::endl;
InitOrder io(5);
std::cout << std::endl;
// ------ 6. Logger — 解構子示範 ------
std::cout << "【6】解構子自動呼叫示範\n" << std::endl;
{
std::cout << " 進入內部區塊" << std::endl;
Logger log1("A");
Logger log2("B");
log1.log("正在工作...");
log2.log("也在工作...");
std::cout << " 即將離開區塊" << std::endl;
}
// log1 和 log2 離開作用域,解構子自動被呼叫
// 注意:解構順序是建構順序的相反(LIFO)
std::cout << "\n 已離開區塊,物件已被銷毀" << std::endl;
std::cout << "\n========================================" << std::endl;
std::cout << " 範例結束" << std::endl;
std::cout << "========================================" << std::endl;
return 0;
}
相关文章
C++
c
更新于 2026-07-21
deviceAlpha.h
deviceAlpha.h — c source code from the C++ learning materials (C++/Mavis_Homework/FinalProject/deviceAlpha.h).
阅读文章 →
C++
c
更新于 2026-07-21
finalproject.c
finalproject.c — c source code from the C++ learning materials (C++/Mavis_Homework/FinalProject/finalproject.c).
阅读文章 →
C++
cpp
更新于 2026-07-21
finalproject.cpp
finalproject.cpp — cpp source code from the C++ learning materials (C++/Mavis_Homework/FinalProject/finalproject.cpp).
阅读文章 →
C++
c
更新于 2026-07-21
deviceAlpha.h
deviceAlpha.h — c source code from the C++ learning materials (C++/Mavis_Homework/Lab8/deviceAlpha.h).
阅读文章 →
C++
c
更新于 2026-07-21
lab8.c
lab8.c — c source code from the C++ learning materials (C++/Mavis_Homework/Lab8/lab8.c).
阅读文章 →
C++
cpp
更新于 2026-07-21
lab8.cpp
lab8.cpp — cpp source code from the C++ learning materials (C++/Mavis_Homework/Lab8/lab8.cpp).
阅读文章 →