下面程序可以正常编译并输出 $10$。
int calc(int x, int y = 10);
int calc(int x) { return x * 2; }
int calc(int x, int y) { return x * y; }
int main() {
cout << calc(5);
}答案B。指针和数组的代码追踪:画出变量和指针的内存示意图,追踪每次赋值后值的变化。
指针和数组追踪时画内存布局图可以大大简化理解。
【考点】函数重载|默认参数|重载匹配规则
考纲定位:GESP 四级 C++ 大纲"函数重载"模块(第 5 章)明确区分声明与定义中默认参数的处理。命题人故意用声明带默认参数、定义却省略该参数的冲突组合,卡住大多数考生对"重载函数签名必须严格一致"的盲点——很多人只背"默认参数可省略",却忽略定义时默认参数必须显式写出。
解题思维:先定位声明 calc(int x, int y = 10),其参数列表含默认值。定义中却出现两个重载:calc(int x) 和 calc(int x, int y)。关键观察是 C++ 重载匹配规则:调用 calc(5) 时,编译器优先匹配声明中的 calc(int x, int y = 10)(因为默认参数允许省略第二个参数),返回 5*10 = 50,而非题目声称的 10。此外,定义中的 calc(int x) 与声明的 calc(int x, int y = 10) 签名不匹配,导致链接阶段无法找到对应实现,程序无法通过编译。
陷阱拆解:选项 A"正确"是命题人精心设计的陷阱。它利用学生"默认参数可省略"的片面记忆,却忽略"定义时必须显式包含所有参数"的硬性规则。更阴险的是,两个定义 calc(int x) 和 calc(int x, int y) 参数类型相同、数量不同,看似是重载,但实际 calc(int x) 无法匹配声明中的 calc(int x, int y = 10),因为声明中 y 有默认值,定义中必须保留该参数。若只背结论、不理解重载匹配流程,必然掉进"输出 10 就认为正确"的坑里。
反命题思维:从命题人角度看,若将声明改为 int calc(int x);,去掉默认参数,定义中的 calc(int x) 与 calc(int x, int y) 便构成合法重载,调用 calc(5) 匹配前者,返回 5*2 = 10,程序正确。若将定义中的 calc(int x) 改为 calc(int x, int y = 10),则与声明一致,调用 calc(5) 匹配后者,返回 5*10 = 50,输出错误。这类变体都能考察同一考点的不同侧面。刷到类似题时,先问自己"命题人想考我什么",再对照重载匹配规则逐项校核。