函数定义ã€å‚数与返回值
è¿™å‘¨ä½ ä¼šä»Žâ€œæŠŠä»£ç 写出æ¥â€å‡çº§ä¸ºâ€œæŠŠä»£ç 组织好â€ã€‚函数å¯ä»¥è®©ä»£ç å¤ç”¨ã€å¯æµ‹è¯•ã€å¯ç»´æŠ¤ï¼Œæ˜¯åŽç»é¡¹ç›®å¼€å‘的关键基础。
å¦å®Œè¿™å‘¨ï¼Œä½ 能自己设计函数ç¾å,知é“ä»€ä¹ˆæ—¶å€™ä¼ å‚æ•°ã€ä»€ä¹ˆæ—¶å€™è¿”回结果。
6.1 函数的价值
å‡½æ•°ä¸æ˜¯ä¸ºäº†â€œçœ‹èµ·æ¥é«˜çº§â€ï¼Œè€Œæ˜¯ä¸ºäº†å‡å°‘é‡å¤å’Œé™ä½Žå¤æ‚度。一个函数尽é‡åªåšä¸€ä»¶äº‹ï¼Œä¸»æµç¨‹ä¼šæ›´æ¸…楚。
6.2 函数ç¾å先行
先写函数åã€å‚æ•°ã€è¿”回类型,å†å†™å‡½æ•°ä½“ã€‚è¿™æ ·èƒ½å…ˆæƒ³æ¸…æ¥šâ€œè¾“å…¥æ˜¯ä»€ä¹ˆã€è¾“出是什么â€ã€‚
double calcAverage(int a, int b, int c) {
return (a + b + c) / 3.0;
}
6.3 傿•°ä¸Žè¿”回值设计
傿•°è´Ÿè´£è¾“入,返回值负责输出结果。尽é‡é¿å…在函数内直接ä¾èµ–外部全局状æ€ï¼Œè¿™æ ·å‡½æ•°æ›´å®¹æ˜“å¤ç”¨å’Œæµ‹è¯•。
int maxOfThree(int a, int b, int c) {
int m = a;
if (b > m) m = b;
if (c > m) m = c;
return m;
}
6.4 函数调试æ€è·¯
- å…ˆå•æµ‹å‡½æ•°ï¼Œå†æŽ¥åˆ°ä¸»æµç¨‹ã€‚
- æ¯ä¸ªå‡½æ•°è‡³å°‘准备 3 组输入。
- 边界值(0ã€ç©ºã€æžå€¼ï¼‰å¿…须覆盖。
- å‡½æ•°å¼‚å¸¸å…ˆçœ‹å‚æ•°å€¼ï¼Œå†çœ‹è¿”回值。
6.5 深度讲解:函数设计的四个关键问题
函数设计看似简å•ï¼ŒçœŸæ£æ‹‰å¼€å·®è·çš„æ˜¯â€œè®¾è®¡å‰æ€è€ƒâ€ã€‚ä½ åœ¨å†™å‡½æ•°å‰è‡³å°‘è¦å›žç”四个问题:这个函数解决什么问题?输入是什么?输出是什么?失败时怎么处ç†ï¼Ÿå¦‚æžœè¿™å››ä¸ªé—®é¢˜ä¸æ¸…楚,函数通常会出现èŒè´£æ··ä¹±ã€å‚æ•°æ··ä¹±ã€è¿”回值ä¸ç¨³å®šç‰é—®é¢˜ã€‚很多åŒå¦ä¼šå†™å‡ºä¸€ä¸ªâ€œä¸‡èƒ½å‡½æ•°â€ï¼Œæ—¢è¯»è¾“å…¥ã€åˆè®¡ç®—ã€åˆæ‰“å°ã€è¿˜ä¿®æ”¹å…¨å±€å˜é‡ï¼ŒçŸæœŸèƒ½è·‘,长期æžéš¾ç»´æŠ¤ã€‚æ£ç¡®åšæ³•æ˜¯æŠŠèŒè´£æ‹†å¼€ï¼šè¯»è¾“入是一个函数,计算是一个函数,展示是一个函数。
函数命åä¹Ÿæ˜¯è®¾è®¡çš„ä¸€éƒ¨åˆ†ã€‚å»ºè®®ä½¿ç”¨â€œåŠ¨è¯ + 对象â€çš„æ¨¡å¼ï¼Œä¾‹å¦‚ `loadScores`ã€`calcAverage`ã€`printReport`。看到åå—就知é“è¡Œä¸ºï¼Œè°ƒè¯•æ—¶å‡ ä¹Žä¸éœ€è¦çŒœã€‚如果函数å太抽象(如 `processData`ã€`doTask`),通常说明函数èŒè´£ä¹Ÿä¸æ¸…晰。命å䏿˜¯è¡¨é¢å·¥ä½œï¼Œè€Œæ˜¯å¸®åŠ©ä½ æ€è€ƒè¾¹ç•Œå’Œè´£ä»»ã€‚ä½ å¯ä»¥ç»™è‡ªå·±ä¸€ä¸ªå°è§„åˆ™ï¼šå¦‚æžœå‡½æ•°åæ— 法在 10 秒内解释清楚这个函数åšä»€ä¹ˆï¼Œé‚£å°±é‡æ–°å‘½åæˆ–é‡æ–°æ‹†åˆ†ã€‚
傿•°æ•°é‡è¦å…‹åˆ¶ã€‚傿•°è¿‡å¤šä¼šæ˜¾è‘—å¢žåŠ è°ƒç”¨é”™è¯¯æ¦‚çŽ‡ï¼Œå°¤å…¶åœ¨å‚æ•°ç±»åž‹ç›¸ä¼¼æ—¶å¾ˆå®¹æ˜“ä¼ é”™ä½ç½®ã€‚比如 `(int a, int b, int c, int d)` 这类ç¾å一旦顺åºé”™ï¼Œç¼–è¯‘å™¨æœªå¿…æŠ¥é”™ä½†ç»“æžœä¼šé”™ã€‚è§£å†³æ–¹æ³•æ˜¯ï¼šæŠŠç›¸å…³å‚æ•°å°è£…æˆç»“æž„ä½“ï¼Œæˆ–è€…æ‹†æˆæ›´å°å‡½æ•°ã€‚åˆå¦é˜¶æ®µå»ºè®®ä¸€ä¸ªå‡½æ•°æŽ§åˆ¶åœ¨ 1 到 3 ä¸ªæ ¸å¿ƒå‚æ•°ï¼Œè¶…过 4 个就考虑是å¦éœ€è¦é‡æž„。
6.6 傿•°ä¼ 递与返回值ç–ç•¥
傿•°ä¼ 递方å¼ä¼šå½±å“æ€§èƒ½å’Œå®‰å…¨æ€§ã€‚å€¼ä¼ é€’æœ€ç›´è§‚ï¼Œä½†ä¼šå‘生拷è´ï¼›å¼•ç”¨ä¼ é€’å¯ä»¥é¿å…æ‹·è´ï¼Œä½†è¦è°¨æ…Žä¿®æ”¹å¤–部数æ®ï¼›`const &` 是åªè¯»å¤§å¯¹è±¡æ—¶æœ€å¸¸è§ã€æœ€ç¨³å¦¥çš„é€‰æ‹©ã€‚ä½ ä¸éœ€è¦ä¸€æ¬¡æŽŒæ¡æ‰€æœ‰ç»†èŠ‚ï¼Œä½†è¦å½¢æˆé€‰æ‹©æ„识:å°è€Œç®€å•的数æ®å¯å€¼ä¼ ,大容器优先 `const &`ã€‚ä¸€æ—¦ä½ å¼€å§‹å¤„ç† `vector`ã€`map`ã€`string` ç‰å¯¹è±¡ï¼Œè¿™ä¸ªä¹ 惯会éžå¸¸é‡è¦ã€‚
返回值方é¢ï¼Œä¼˜å…ˆè®©å‡½æ•°è¿”回“完æˆä»»åŠ¡æ‰€éœ€çš„æœ€å°ç»“æžœâ€ã€‚ä¸è¦ä¾èµ–“顺便修改外部å˜é‡â€æ¥ä¼ 递结果,这会让函数行为å˜å¾—éšè”½ã€‚比如计算平å‡åˆ†å°±è¿”回一个 `double`ï¼›éªŒè¯æ˜¯å¦åˆæ³•就返回 `bool`。如果函数å¯èƒ½å¤±è´¥ï¼Œå¯ä»¥è¿”回状æ€å€¼å¹¶åœ¨è°ƒç”¨æ–¹å¤„ç†ã€‚å†™ç¨‹åºæ—¶è¯·å°½é‡æŠŠâ€œä¸šåŠ¡é€»è¾‘â€å’Œâ€œå±•示输出â€åˆ†å¼€ï¼šè®¡ç®—函数返回结果,打å°å‡½æ•°åªè´Ÿè´£å±•ç¤ºã€‚è¿™æ ·ä½ åŽç»åšå•元测试会轻æ¾å¾ˆå¤šã€‚
bool parseScore(int input, int& output) {
if (input < 0 || input > 100) return false;
output = input;
return true;
}
double calcAverage(const vector<int>& scores) {
if (scores.empty()) return 0.0;
long long sum = 0;
for (int s : scores) sum += s;
return static_cast<double>(sum) / scores.size();
}
6.7 å‡½æ•°è°ƒè¯•ä¸Žé‡æž„æµç¨‹
推èä½ ä½¿ç”¨â€œå…ˆå•æµ‹å‡½æ•°ï¼Œå†æ•´åˆä¸»æµç¨‹â€çš„ç–略。先给æ¯ä¸ªå‡½æ•°å‡†å¤‡æœ€å°æµ‹è¯•:æ£å¸¸å€¼ã€è¾¹ç•Œå€¼ã€å¼‚常值。函数å•独通过åŽï¼Œå†æ”¾è¿›ä¸»æµç¨‹ã€‚è¿™æ ·ä¸€æ—¦ç»“æžœå¼‚å¸¸ï¼Œä½ å¯ä»¥å¿«é€Ÿåˆ¤æ–是函数本身问题还是调用问题。很多åŒå¦è°ƒè¯•æ•ˆçŽ‡ä½Žï¼Œæ˜¯å› ä¸ºä¸€å¼€å§‹å°±åœ¨å®Œæ•´ç³»ç»Ÿé‡ŒæŽ’æŸ¥ï¼Œé—®é¢˜èŒƒå›´å¤ªå¤§ã€‚æŠŠé—®é¢˜åˆ‡å°ï¼Œæ•ˆçŽ‡ä¼šç«‹åˆ»æå‡ã€‚
釿ž„æ—¶å¯ä»¥éµå¾ªä¸‰æ¥ï¼šç¬¬ä¸€æ¥ï¼Œå¤åˆ¶æ—§å‡½æ•°å¹¶å‘½å为新版本;第二æ¥ï¼Œå°æ¥æ”¹åŠ¨å¹¶æ¯æ¥è¿è¡Œï¼›ç¬¬ä¸‰æ¥ï¼ŒéªŒè¯æ–°æ—§è¡Œä¸ºä¸€è‡´å†åˆ 除旧版本。这个æµç¨‹èƒ½é¿å…â€œæ”¹ç€æ”¹ç€å…¨å´©â€ã€‚æ¤å¤–ï¼Œç»™å…³é”®å‡½æ•°å†™ç®€çŸæ³¨é‡Šï¼ˆè¾“å…¥ã€è¾“出ã€è¾¹ç•Œå‡è®¾ï¼‰ä¹Ÿå¾ˆæœ‰ä»·å€¼ã€‚䏿˜¯å†™é•¿ç¯‡æ–‡æ¡£ï¼Œè€Œæ˜¯å†™èƒ½è®©æœªæ¥çš„ä½ ä¸‰ç§’è¯»æ‡‚å‡½æ•°ç›®çš„çš„è¯´æ˜Žã€‚
函数能力是第二阶段最é‡è¦çš„分水å²ã€‚ä½ èƒ½æŠŠåŠŸèƒ½å†™å‡ºæ¥ï¼Œæ˜¯â€œä¼šåšé¢˜â€ï¼›ä½ 能把功能拆æˆå¯å¤ç”¨å‡½æ•°å¹¶ç¨³å®šè¿ä»£ï¼Œæ‰æ˜¯â€œä¼šå¼€å‘â€ã€‚第6周请把精力放在设计质é‡ä¸Šï¼Œä¸è¦åªè¿½æ±‚“跑通一次â€ã€‚
6.8 è¯¾å ‚é—®ç”与进阶练ä¹
问:函数越多越好å—? 䏿˜¯ã€‚函数数é‡ä¸æ˜¯ç›®æ ‡ï¼ŒèŒè´£æ¸…æ™°æ‰æ˜¯ç›®æ ‡ã€‚一个 60 行但èŒè´£å•一的函数,比 6 个互相耦åˆçš„å°å‡½æ•°æ›´å¥½ç»´æŠ¤ã€‚åˆ¤æ–æ ‡å‡†æ˜¯ï¼šè¿™ä¸ªå‡½æ•°èƒ½ä¸èƒ½ç”¨ä¸€å¥è¯è¯´æ¸…楚它åšä»€ä¹ˆï¼›å¦‚æžœä¸èƒ½ï¼Œä¼˜å…ˆæ‹†åˆ†èŒè´£ï¼Œè€Œä¸æ˜¯æœºæ¢°è¿½æ±‚“函数数é‡â€ã€‚
问:我能ä¸èƒ½åœ¨å‡½æ•°é‡Œç›´æŽ¥ `cout` 结果,çœå¾—返回值? å¯ä»¥ï¼Œä½†è¦çœ‹åœºæ™¯ã€‚è‹¥å‡½æ•°æ ¸å¿ƒæ˜¯â€œè®¡ç®—â€ï¼Œå»ºè®®è¿”å›žå€¼ï¼›è‹¥å‡½æ•°æ ¸å¿ƒæ˜¯â€œå±•ç¤ºâ€ï¼Œå¯ä»¥ `cout`。把计算与展示分开,åŽç»åšæµ‹è¯•å’Œå¤ç”¨ä¼šæ›´è½»æ¾ã€‚æ¯”å¦‚ä½ è¦æŠŠç»“æžœå†™å…¥æ–‡ä»¶æˆ–å‘é€åˆ°ç½‘ç»œæ—¶ï¼Œè¿”å›žå€¼æ–¹æ¡ˆå‡ ä¹Žæ€»æ˜¯æ›´çµæ´»ã€‚
é—®ï¼šä¸ºä»€ä¹ˆæˆ‘è°ƒç”¨å‡½æ•°æ—¶æ€»ä¼ é”™å‚æ•°é¡ºåºï¼Ÿ 说明函数ç¾åä¸å¤Ÿå‹å¥½ï¼Œæˆ–è€…å‚æ•°å«ä¹‰ä¸å¤Ÿæ¸…æ¥šã€‚ä½ å¯ä»¥ç”¨ä¸¤ç§æ–¹å¼æ”¹è¿›ï¼šç¬¬ä¸€ï¼Œç»™å‚数起更明确的åå—ï¼›ç¬¬äºŒï¼ŒæŠŠå¼ºç›¸å…³å‚æ•°å°è£…æˆç»“构体,å‡å°‘ä½ç½®é”™è¯¯ã€‚调用错误并ä¸ä¸¢äººï¼Œå®ƒæ˜¯æé†’ä½ æ”¹è¿›æŽ¥å£è®¾è®¡çš„ä¿¡å·ã€‚
è¿›é˜¶ç»ƒä¹ å»ºè®®ï¼šåˆ¶ä½œâ€œæˆ˜æ–—å›žåˆè®¡ç®—模å—â€ã€‚拆分为 `calcDamage`ã€`isCriticalHit`ã€`applyDefense`ã€`printBattleLog` å››ä¸ªå‡½æ•°ï¼Œè¦æ±‚: 第一,计算函数ä¸ç›´æŽ¥è¾“出,由展示函数统一输出; 第二,所有函数都写明输入和返回值å«ä¹‰ï¼› 第三,至少准备 10 组测试,覆盖高攻低防ã€ä½Žæ”»é«˜é˜²ã€æš´å‡»è§¦å‘ã€è¾¹ç•Œå€¼ç‰åœºæ™¯ã€‚ 完æˆåŽå†åšä¸€æ¥é‡æž„:把常é‡ï¼ˆå¦‚暴击å€çŽ‡ï¼‰æŠ½æˆå‘½å常é‡ï¼ŒéªŒè¯ç»“æžœä¿æŒä¸€è‡´ã€‚
ä½ è¿˜å¯ä»¥åšâ€œå‡½æ•°æ›¿æ¢å®žéªŒâ€ï¼šå…ˆç”¨ä¸€æ®µé•¿é€»è¾‘实现åŒä¸€åŠŸèƒ½ï¼Œå†ç”¨å‡½æ•°æ¨¡å—化é‡å†™ï¼Œæ¯”较两ç§ç‰ˆæœ¬åœ¨å¯è¯»æ€§ã€è°ƒè¯•速度ã€å‡ºé”™çŽ‡ä¸Šçš„å·®å¼‚ã€‚è¿™ä¸ªå®žéªŒä¼šè®©ä½ ç›´è§‚ä½“ä¼šä¸ºä»€ä¹ˆå·¥ç¨‹é¡¹ç›®å‡ ä¹Žéƒ½ç¦»ä¸å¼€å‡½æ•°è®¾è®¡ã€‚
6.9 æœ¬å‘¨ç»ƒä¹ ä¸Žè‡ªæµ‹æ¸…å•
本周练ä¹
- 实现 `calcAverage`ã€`calcMax`ã€`calcMin`ã€`isPass` 四个函数。
- 用这些函数拼出一个完整æˆç»©åˆ†æžç¨‹åºã€‚
- æäº¤è‡³å°‘ 8 组函数测试记录。
自测清å•
- 函数是å¦åªæ‰¿æ‹…å•一èŒè´£ã€‚
- 函数åä¸Žå‚æ•°å是å¦ä¸€çœ‹å°±æ‡‚。
- 函数是å¦èƒ½åœ¨å…¶ä»–场景å¤ç”¨ã€‚
- 我能解释为什么选这个返回类型。
è¡¥å……å»ºè®®ï¼šæ¯æ¬¡æäº¤å‰éšæœºæŠ½ 2 个函数åšâ€œç›²è¯»æµ‹è¯•â€ï¼Œçœ‹ä¸çœ‹å‡½æ•°ä½“åªçœ‹ç¾å和命å,能å¦è¯´å‡ºä½œç”¨ã€‚è‹¥è¯´ä¸æ¸…,优先改接å£å†æ”¹å®žçŽ°ã€‚