← 练习册目录

第 6 章 模板

red wenzi · 2026-09-15 · 编程语言 · C++ · 练习册 · 9 题
📝 本章练习:9 题(A 识别 / B 理解 / C 改错 / D 写程序)。先自己做完再看答案——A、B 档不翻书做,C、D 档必须真的编译运行。

6.1 函数模板与类模板

A1识别判断题:模板在编译期实例化——你写了 maxOf(3, 5),编译器就生成一个 int 版本的函数。

答:______________

✅ 查看答案与解析

答案 对

解析:模板不是“能装任何类型的代码”,而是模具。实例化发生在使用点。

A2识别判断题:Java 泛型是擦除过的(底层 Object[]),C++ 模板是真实的(vector<int> 就是连续 int,没有一层间接)。

答:______________

✅ 查看答案与解析

答案 对

解析:这也是算法竞赛和数据结构课偏爱 C++ 的原因之一:零开销抽象。

B1理解选择题:maxOf(3, 5)(template <typename T> T maxOf(T a, T b))会被实例化为?

maxOf<long long>

maxOf<int>

maxOf<double>

不实例化,运行时判断

答:______________

✅ 查看答案与解析

答案 B

解析:实参 3、5 都是 int,编译器推导 T = int,实例化为 maxOf<int>。

C1应用改错题:下面的模板调用编译报错,为什么?
template <typename T>
T maxOf(T a, T b) { return a > b ? a : b; }
auto m = maxOf(3, 2.5);   // 报错:T 推导冲突(int vs double)
✅ 查看答案与解析

答案 两个实参类型不一致,T 无法同时推导成 int 和 double。显式指定:maxOf<double>(3, 2.5)

解析:T 只能是一个类型。要么实参同型,要么显式指定模板参数。

D1创造写程序:写一个模板函数 maxOf,用 int、double、std::string 三种类型分别调用并输出结果。

提示:std::string 的 > 比较字典序。

✅ 查看答案与解析

答案 参考答案:

解析:同一份模板自动适配三种类型,这就是泛型。

#include <iostream>
#include <string>
template <typename T>
T maxOf(T a, T b) { return a > b ? a : b; }
int main() {
    std::cout << maxOf(3, 5) << '\n';                    // 5
    std::cout << maxOf(1.5, 2.5) << '\n';                // 2.5
    std::cout << maxOf(std::string("ab"), std::string("cd")) << '\n';  // cd
    return 0;
}

6.2 模板为什么必须写在头文件里

A1识别判断题:模板的定义必须放在头文件里,和普通函数(声明进头文件、定义进 .cpp)正好相反。

答:______________

✅ 查看答案与解析

答案 对

解析:模板只有被实例化时才生成代码,实例化发生在使用它的源文件里,编译器必须能看到完整定义。

B1理解选择题:为什么模板不能像普通函数那样“声明放头文件、定义放 .cpp”?

标准不允许

模板没有声明只有定义

模板只有被实例化时才生成代码,而实例化发生在使用它的源文件,编译器必须看到完整定义

编译器偷懒

答:______________

✅ 查看答案与解析

答案 C

解析:普通函数的定义在链接期合并;模板没有“链接”这回事,它在每个使用点现场生成代码,所以定义必须可见。

C1应用改错题:下面把模板定义放在 .cpp 里,main.cpp 调用时报链接错误(undefined reference)。
// mylist.h:只有声明
template <typename T> T pickFirst(const std::vector<T>& v);
// mylist.cpp:定义
template <typename T> T pickFirst(const std::vector<T>& v) { return v[0]; }
✅ 查看答案与解析

答案 把模板的完整定义移到头文件 mylist.h 里(声明和定义都放头文件)。

解析:模板实例化发生在使用点,main.cpp 里看不到定义就无法生成代码。工程上可用 .tpp/.ipp 文件在头文件末尾 #include 进来,本质仍是“使用方能看到定义”。

D1创造写程序:写一个模板类 Stack<T>(内部用 std::vector<T>),实现 push、pop、top、empty,main 里用 int 和 std::string 各测一次。

提示:pop 前检查 empty()。

✅ 查看答案与解析

答案 参考答案:

解析:类模板使用时必须写出具体类型 Stack<int>;类模板定义整体放头文件(此处同文件演示)。

#include <iostream>
#include <string>
#include <vector>
template <typename T>
class Stack {
public:
    void push(const T& v) { data_.push_back(v); }
    void pop() { if (!data_.empty()) { data_.pop_back(); } }
    T& top() { return data_.back(); }
    bool empty() const { return data_.empty(); }
private:
    std::vector<T> data_;
};
int main() {
    Stack<int> si;
    si.push(1); si.push(2);
    std::cout << si.top() << '\n';          // 2
    Stack<std::string> ss;
    ss.push("hi"); ss.push("yo");
    std::cout << ss.top() << '\n';          // yo
    return 0;
}
📚 相关概念:编译与链接 · STL · map / set · 迭代器