模板小结与章测验

模板使我们能够使用占位类型编写函数或类,从而利用不同实际类型“拓印”出同一函数或类的相同实例。被实例化后的函数或类称为函数实例类实例

所有模板函数或模板类都必须以模板形参声明开头,以告知编译器随后的函数或类是模板。在模板形参声明中,可以指定模板类型形参表达式形参。模板类型形参只是占位类型,通常命名为 TT1T2 或其他单字母名称(如 S)。表达式形参多为整型,但也可以是指针或引用(指向函数、类对象或成员函数)。

模板类的定义与成员函数定义不能像普通类那样拆分——不能把类定义放在头文件而把成员函数定义放进 .cpp 文件。通常最佳做法是把所有内容放在同一个头文件中,成员函数定义紧跟在类定义之后。

模板特化用于在特定类型上覆盖模板函数或模板类的默认行为。若对所有类型都进行覆盖,称为完全特化。类还支持部分特化,即只对部分模板参数进行特化;函数模板则不能部分特化。

C++ 标准库中的许多类都使用模板,例如 std::arraystd::vector。模板常用于实现容器类,以便“一次编写,通用于所有合适类型”。


测验

题 1

有时我们需要定义成对出现的数据。请编写一个名为 Pair1 的模板类,允许用户指定一个模板类型用于两个成员。下列程序应能正常运行:

int main()
{
    Pair1<int> p1 { 5, 8 };
    std::cout << "Pair: " << p1.first() << ' ' << p1.second() << '\n';

    const Pair1<double> p2 { 2.3, 4.5 };
    std::cout << "Pair: " << p2.first() << ' ' << p2.second() << '\n';

    return 0;
}

并输出:

Pair: 5 8
Pair: 2.3 4.5

题 2

编写一个名为 Pair 的类,允许用户为两个成员分别指定不同类型。 (注意:之所以换名,是因为 C++ 目前不允许仅因模板参数个数或类型不同就对同名类进行“重载”。)

下列程序应能正常运行:

int main()
{
    Pair<int, double> p1 { 5, 6.7 };
    std::cout << "Pair: " << p1.first() << ' ' << p1.second() << '\n';

    const Pair<double, int> p2 { 2.3, 4 };
    std::cout << "Pair: " << p2.first() << ' ' << p2.second() << '\n';

    return 0;
}

并输出:

Pair: 5 6.7
Pair: 2.3 4

提示:若要使用两种不同类型,只需在模板形参声明中用逗号分隔即可。参见在课程《带多个模板类型的函数模板》中。

题 3

字符串-值对是一种特殊配对:第一个成员固定为字符串类型,第二个成员可为任意类型。请编写模板类 StringValuePair,它继承自部分特化的 Pair 类(第一个类型固定为 std::string,第二个类型由用户指定)。

下列程序应能正常运行:

int main()
{
    StringValuePair<int> svp { "Hello", 5 };
    std::cout << "Pair: " << svp.first() << ' ' << svp.second() << '\n';

    return 0;
}

并输出:

Pair: Hello 5

提示:在 StringValuePair 的构造函数中调用 Pair 构造函数时,别忘了在 Pair 类名后带上模板实参。

关注公众号,回复"cpp-tutorial"

可领取价值199元的C++学习资料

公众号二维码

扫描上方二维码或搜索"cpp-tutorial"