C++_类模板(二)

发布时间:2026/10/15 19:34:42

C++_类模板(二) 模板型成员类型模板型成员类型又称成员类模板是定义在类模板内部的类模板。它允许类模板中包含一个或多个依赖于不同类型参数的嵌套类模板。一个类模板的成员是另一个类模板templatetypename X class A { public: templatetypename Y class B { // B 是一个依赖于类型参数 Y 的类模板 }; };该语法结构使得B可以独立于外部类模板的实例化而被实例化且其类型参数与外层类模板无关。A类模板只需声明或定义无需实例化即可支持B的定义。使用示例#include iostream using namespace std; templatetypename T class A { public: templatetypename D class B { public: templatetypename R void foo() { cout foo endl; } }; }; // 成员函数模板的定义必须在类外显式写出 templatetypename T templatetypename D templatetypename R void AT::BD::foo() { cout foo endl; } int main(void) { Adouble::Bfloat q; q.fooshort(); return 0; }Adouble实例化后生成一个名为Bfloat的类。q.fooshort()调用的是Bfloat内部的fooshort函数模板实例。所有层级的模板参数必须在调用时明确指定。类模板中的成员虚函数类模板可以包含普通成员虚函数这些虚函数支持多态行为其机制与非模板类一致。特性说明支持虚函数类模板可以定义virtual成员函数。支持多态通过基类指针调用派生类重写的虚函数可实现运行时绑定。不支持虚函数模板不能在类模板中声明virtual templatetypename R void bar();这样的语法。原因分析虚函数表vtable是在类实例化时由编译器构建的。成员函数模板具有延迟实例化特性只有当函数被实际调用时才会生成具体函数体。在创建虚函数表时成员函数模板尚未实例化无法确定其地址。因此编译器不允许将函数模板声明为虚函数。正确写法示例#include iostream using namespace std; templatetypename T class A { public: virtual void foo() { cout AT::foo endl; } // ❌ 错误不能声明虚函数模板 // virtual templatetypename R void bar(); // ✅ 正确普通成员函数 void bar() { cout AT::bar endl; } }; templatetypename T, typename D class B : public AT { public: void foo() override { cout BT,D::foo endl; } }; int main(void) { Bint, double b; Aint* p b; p-foo(); // 多态调用输出 Bint,double::foo // p-bar(); // 正常调用但无虚函数机制 return 0; }数值型类型形参模板的类型形参不仅可以是类型名还可以是整数常量数值型参数用于控制模板行为。语法格式templatetypename T, int S 10 class Array { // ... };示例templatetypename T, int SIZE 10 class Array { private: T data[SIZE]; public: void print() const { for (int i 0; i SIZE; i) cout data[i] ; cout endl; } }; int main() { Arrayint, 5 arr1; // 指定大小为 5 Arraydouble arr2; // 使用默认大小 10 return 0; }支持缺省值如int SIZE 10。数值参数必须是编译时常量表达式。不支持浮点数、字符串等非整型常量。模板型类型形参模板的类型形参也可以是另一个类模板即模板模板参数用于接收模板作为参数。语法格式templatetemplatetypename class C Array class Sum { // ... };示例templatetypename T class Array { public: T data[10]; }; templatetypename T class List { public: T data[10]; }; templatetemplatetypename class Container Array class Sum { public: void add() { cout Using container type endl; } }; int main() { SumArray s1; // 显式指定容器类型 SumList s2; // 使用不同的模板 Sum s3; // 使用默认模板 Array return 0; }Container是一个模板模板参数表示接受一个单参数模板。必须使用templatetypename来限定其形式。若需更复杂的模板如双参数模板则需额外处理。模板二次编译机制编译器对模板进行两次编译这是理解模板错误的关键。第一次编译模板定义阶段发生在模板实例化之前。编译器仅检查模板本身的语法和基本语义。对于已知类型检查成员访问是否合法。对于未知类型如模板参数假设所有操作都合法。不会检查函数调用的实际有效性。第二次编译实例化阶段发生在模板被具体类型实例化之后。结合实际使用的类型实参重新检查所有代码。此时才能确定函数是否存在、成员是否可访问。错误示例解析#include iostream using namespace std; class A { public: void foo() {} }; templatetypename T void bar() { // gdjgjkgsfgkldd; // ❌ 第一次编译报错标识符未声明 A a; a.foo(); // ✅ 第一次编译通过a.foo() 合法 // a.fjoidjg(); // ❌ 第一次编译报错不存在该函数 T t; t.djfoijdf(); // ✅ 第一次编译通过假设存在 // t.djfoidfsdfsdjifod(); // ❌ 第一次编译报错非法使用 } int main() { barA(); // 触发实例化进入第二次编译 // 此时才检查 t.djfoijdf() 是否有效 —— 实际不存在报错 return 0; }关键结论第一次编译只做语法合法性检查不关心具体类型。第二次编译才真正验证调用的有效性。所有模板错误最终在实例化时暴露。避免在模板中使用未经验证的成员调用尤其是针对模板参数类型的成员。总结要点特性是否支持说明成员类模板模板型成员类型✅可在类模板内定义嵌套类模板成员虚函数✅支持多态可用于继承体系成员虚函数模板❌无法构建虚函数表因实例化延迟数值型模板参数✅整数常量可设缺省值模板模板参数✅接收类模板作为参数需templatetypename修饰二次编译机制⚠️先检查语法再结合实参验证有效性掌握这些规则有助于避免常见模板编程错误提升代码健壮性与可维护性。
延伸阅读

更多相关文章

2026/10/15 19:34:42

期刊AI率合格线是多少?知网和维普AIGC检测该怎么选?

投稿前查重大家都知道要做,但查AIGC很多人会漏掉,这一步现在和查重一样重要。 别以为自己写的稿子就没有AI率。检测系统看的是句式特征,不管是不是你亲手写的,套路化的综述、总结段落都可能被标红,测出20%-30%很常见。…

2026/10/15 19:34:42

AI 自动化逆向(六)AI 解一个 9 万条目的资源容器

AI 自动化逆向(六)AI 解一个 9 万条目的资源容器 本文是「AI 自动化逆向」系列第 6 篇。上一篇:控制组:区分「没有」和「没取到」;下一篇预告:AI 一旦找到单一指标就会崇拜它。 前言 上一篇讲的是"空…

2026/10/15 19:29:34

财务共享服务中心建设指南:流程再造与系统落地全解析

简介:财务共享服务解决方案资料包,面向企业财务管理人员、共享服务中心建设团队与财务信息化从业者,聚焦财务共享服务中心的整体技术架构、建设路径与行业应用,旨在帮助企业财务核算转型与集中作业实施中梳理组织边界和系统落地路…

2026/10/16 3:11:26

AppXApplicabilityBlob.dll丢失别下载!SFC+DISM官方修复法

先说一句可能跟标题不太一样的话:AppXApplicabilityBlob.dll 这个文件提示丢失,我建议你先别急着满世界找“免费下载”,因为大概率你是被各种下载站坑过的。这个文件是 Windows 系统里跟商店应用(AppX 包)的部署、卸载…

2026/10/16 3:11:26

draw.io 离线绘图安装教程:3步免费装好,覆盖三平台

draw.io 离线绘图安装教程:3步免费装好,覆盖三平台 【免费下载链接】drawio-desktop Official electron build of draw.io 项目地址: https://gitcode.com/GitHub_Trending/dr/drawio-desktop draw.io 桌面版是一款免费的离线绘图工具&#xff0c…

2026/10/16 3:11:26

基于Spring Boot的无人机农田巡查系统设计与实现指南

每到毕业季,总有人问我,Java 后端适合做什么样的毕业设计。我的回答里经常会出现一个方向:基于 Spring Boot 的无人机农田巡查系统。这个题目的好处太明显了——它不是一个单纯的增删改查管理系统,而是把设备管理、地图、任务流、…

2026/10/16 3:11:26

AI生成教材如何降低查重率?从根因到参数调优的完整方案

当AI开始承担教材初稿的撰写,最先撞上的往往不是写作能力,而是查重率这个硬指标。不少用AI生成教材的朋友都有过这种经历:明明每句话读起来通顺正常,丢进查重系统一跑,重复率直奔三四十甚至更高。这里要明确一个前提&a…

2026/10/16 3:11:26

设备保养不是换油擦灰,做到真正有效还差这4步

设备保养最让人头疼的是什么? 不是没人干,而是保养天天做,设备照样坏。 润滑油按时换了,设备表面擦干净了,螺丝也拧紧了,保养记录一张没少。结果没过几天,轴承又发热、皮带又打滑,同…

2026/10/16 3:06:26

基于C++实现三次样条插值功能以及工程应用

目录 1.1 核心原理 1.2 解决的问题 1.3 目的 2. 样条的性质(基于数值分析教材) 3. 代码、函数详细说明 3.1 Lei_SplineInterpolator.h代码 3.2 Lei_SplineInterpolator.cpp代码 3.3 main函数测试代码 3.4运行结果 3.6 函数说明 ◆ Lei_Spline…

2026/10/14 11:31:03

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/14 17:41:07

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/15 13:42:16

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/16 0:01:11

Cephadm实战指南:Linux系统工程师的生产级Ceph集群部署与排障

简介:本资源是一份完整的Ceph分布式存储系统中文技术文档合集,面向Linux系统运维工程师、云平台架构师及存储方向开发者,帮助读者系统掌握Ceph集群的部署、配置与运维核心能力。文档覆盖对象存储(RGW)、块设备&#xf…

2026/10/16 0:01:11

ITK中SpatialObject几何体系解析:坐标系、变换与管道集成

1. 空间对象的定位:为什么 ITK 需要一套几何描述体系很多刚开始接触 ITK 的朋友,包括我自己,最初都是被它的图像滤波、配准、分割这些“正统”功能吸引进来的。等真正上手做点实际项目,比如把分割出来的器官边界做量化分析、给血管…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑