C++ V2 · TYPED FOUNDATIONS · 51
Type / Operator / if:C++ 的型別不是註解,而是程式 Contract 的一部分
C++ source 在 process 執行前,先經 compiler 檢查大量型別與語法規則。這一課不是背 int、double,而是建立「expression 先按 operand types 求值,再把結果存進 target type」的精確模型。
Learning outcomes
- 能拆解 declaration 中的 type、identifier、initializer。
- 能預測 integer / floating-point arithmetic 與 conversion。
- 能用 Boolean expression 寫 typed business rule。
- 能區分 compile-time type error 與 compile 成功後的 logic error。
- 能用 compiler warning 與 boundary cases 驗證假設。
1. Why now:C++ 在「執行之前」就會拒絕一部分程式
int score = 90;
double average = 87.5;
int invalid = "ninety";
// compile error
JavaScript 常把型別問題留到 runtime;C++ 會把大量 constraints 放進 source-level type system。這不是「比較嚴格」這麼簡單,而是 failure layer 改變了。
2. Mental model:Declaration 同時建立名稱與型別約束
int score = 90;
int
→ declared type
score
→ identifier
90
→ initializer expression
之後 compiler 會用 score 的 type 參與 expression checking、overload resolution 與 conversion。
3. Worked Example A:int division 先發生,再存進 double
int total = 7;
int count = 2;
double average =
total / count;
std::cout
<< average;
// 3.0
右側 int / int 先得到整數 3,再轉成 double 3.0。左邊宣告 double 不會回頭改寫右側運算規則。
4. Execution trace:Expression Type 要一步一步算
total : int = 7
count : int = 2
total/count:
int / int
→ int 3
assign to:
double average
→ 3.0
這種 trace 比「C++ 會自動轉型」更精確,因為 conversion 發生在哪一步會直接影響結果。
5. Worked Example B:明確轉成 floating-point
double average =
static_cast(
total
) / count;
std::cout
<< average;
// 3.5
現在左 operand 已經是 double,因此 division 進入 floating-point arithmetic。
6. Narrowing:資料「裝得進去」也可能失去資訊
double exact = 3.8;
int truncated =
static_cast(
exact
);
std::cout
<< truncated;
// 3
Conversion 不代表語意一定正確。你仍需知道是否允許 truncation、overflow 或 precision loss。
7. const:把「不應修改」變成 compiler 可檢查的 Constraint
const int passScore = 60;
// passScore = 50;
// compile error
對固定規則使用 const 能把設計意圖轉成編譯期約束。
8. Worked Example C:Condition 是 Typed Expression 的結果
int score = 72;
const int passScore = 60;
const bool passed =
score >= passScore;
if (passed) {
std::cout << "Pass
";
} else {
std::cout << "Fail
";
}
score >= passScore 的結果是 bool;if 消費這個 condition。
9. Rule Ordering:多條件時先定義 Business Boundary
std::string label;
if (score >= 90) {
label = "Excellent";
} else if (score >= 60) {
label = "Pass";
} else {
label = "Fail";
}
如果先寫 score >= 60,90 分也會先進 Pass branch。這不是 compiler error,是 rule ordering logic error。
10. Common mistakes
A. 以為 target type 會改變 expression type
double x = 5 / 2 仍先做 int division。
B. 混淆 assignment 與 comparison
= 與 == 是不同操作;warning 設定可以協助發現可疑寫法。
C. 把 compile 成功等同邏輯正確
60 分邊界寫成 > 60 一樣會成功 build。
D. 無視 input failure
std::cin >> score 失敗會改變 stream state;不能假設所有輸入都合法。
11. Debug evidence:Compiler 與 Runtime Evidence 分開
g++ -std=c++20
-Wall
-Wextra
-pedantic
main.cpp
-o grade-analyzer
Compiler diagnostic 回答 source/type 層問題;如果 executable 已成功產生但結果錯,才進 execution trace 與 boundary tests。
12. Guided exercise:預測再 Compile
int a = 5;
int b = 2;
double x = a / b;
double y =
static_cast(a)
/ b;
先寫 x/y 預測值與每一步 expression type,再實際 compile/run 驗證。
13. Independent exercise:Typed Score Rule
建立 CLI:輸入 score,輸出 Invalid / Fail / Pass / Excellent。規則:
valid: 0..100
Excellent: 90..100
Pass: 60..89
Fail: 0..59
至少測 -1、0、59、60、89、90、100、101。
14. Challenge:Input Stream Failure
int score = 0;
std::cin >> score;
if (!std::cin) {
// what now?
}
輸入 abc,觀察 stream state。說明這與「score out of range」是不同種類的 validation failure。
Project checkpoint:CLI Grade Analyzer · Typed Core v1
stdin
↓ parse typed input
int score
↓ validate range
0..100
↓ classify
Excellent / Pass / Fail
↓
stdout
這一版只處理一筆 score;52 會把規則拆成 function 並處理多筆。
15. Vocabulary / Summary
- static type:compiler 在 build 時已知的 type。
- conversion:把 value 轉成另一 type representation。
- narrowing:可能失去 range/precision 的 conversion。
- expression type:expression 求值時依 operands/operator 決定的 type。
- logic error:build/run 都成功但 behavior 不符合 contract。
16. Further reading
Knowledge check · Mastery
- 解釋
double x = 5 / 2;為何是 2.0。 - 完成 8 個 score boundary cases。
- 區分 input parse failure、range failure 與 logic error。
- 完成頁面下方 C++ compile/trace practice。