课程代码仓库初始化:Part1 (144) + Part3 (29) 全量生成与验证

把川大 wiki「02.Qt方向」课程代码整理为 CMake 管理的可编译运行项目。

Part1 C/C++ 强化 (p01/, 144 目标, host gcc/g++ 构建, 全绿):
- 修复全部编译失败:补 <cstring>/<fstream>/<iomanip>/<vector> 等缺失头
  (common_fix + infer_stl_includes 自动检测注入)、修正 pause() 壳注入
  (改检测已转换后的 pause 调用)、namespace 提升出函数体、const 成员函数
  正确性、dedupe 不再破坏函数重载集、K&R 隐式 int / 动态异常规范等
  C++17 移除特性的可编译等价改写。
- 目录采用深缩写 p01/ch04/s03/ (原 part1_cpp/ch04_class_object/03_ctor_dtor)。

Part3 Qt 桌面 (p03/, 29 目标, 隔离 Qt 5.14.2 构建, 全绿):
- gen_part3.py: Qt 外壳模板 (main+QApplication+show, QTimer 自动退出便于
  offscreen 验证)、AUTOMOC + .moc include、rewrite_* 处理散文混入/重载/
  资源依赖、生成占位 png/gif + .qrc + rundata 样例数据。
- 修正 QLable 笔误、全角分号、.→->、Windows 路径、QApplication 阻塞事件
  循环改为 QCoreApplication 等。

任务1 概念/版本验证:
- tools/std_probe.py: 跨 -std= 编译探针 (--pedantic-errors 让已废除特性硬失败)。
- tools/demo_versions/: K&R 隐式 int、三目左值、void* 转换、enum 赋整、
  const 经指针、动态异常规范 共 6 个跨版本演示。
- docs/VERSION_NOTES.md: 每条「原文说法→C17/C++17 是否成立→何版本成立→已验证」。

文档: 顶层 README、docs/SOURCE_PAGES.md (页面→目录映射)、
docs/ERRATA.md (Part1 修正)、docs/ERRATA_part3.md (Part3 修正)。
另修复 tools/run.sh / run_qt.sh 的 ${1:?...} 引号语法 bug。

隔离 Qt 验证: ldd 0 系统 Qt 引用; 173/173 目标全绿; p03 offscreen 运行通过。
This commit is contained in:
张宗平
2026-06-30 14:16:55 +08:00
commit 13b3ebbe14
287 changed files with 16532 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
# Auto-generated by tools/gen_part1.py — do not edit by hand.
# 章节:p01/ch05
add_executable(p1c05_01 function_template.cpp)
set_target_properties(p1c05_01 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_01 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_01 PRIVATE -Wall -Wextra)
add_executable(p1c05_02 template_vs_function.cpp)
set_target_properties(p1c05_02 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_02 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_02 PRIVATE -Wall -Wextra)
add_executable(p1c05_03 template_call_rules.cpp)
set_target_properties(p1c05_03 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_03 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_03 PRIVATE -Wall -Wextra)
add_executable(p1c05_04 template_limitations.cpp)
set_target_properties(p1c05_04 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_04 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_04 PRIVATE -Wall -Wextra)
add_executable(p1c05_05 class_template_basics.cpp)
set_target_properties(p1c05_05 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_05 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_05 PRIVATE -Wall -Wextra)
add_executable(p1c05_06 class_template_as_param.cpp)
set_target_properties(p1c05_06 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_06 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_06 PRIVATE -Wall -Wextra)
add_executable(p1c05_07 class_template_derives_class.cpp)
set_target_properties(p1c05_07 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_07 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_07 PRIVATE -Wall -Wextra)
add_executable(p1c05_08 class_template_derives_template.cpp)
set_target_properties(p1c05_08 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_08 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_08 PRIVATE -Wall -Wextra)
add_executable(p1c05_09 class_template_in_class_impl.cpp)
set_target_properties(p1c05_09 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_09 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_09 PRIVATE -Wall -Wextra)
add_executable(p1c05_10 class_template_out_of_class_impl.cpp)
set_target_properties(p1c05_10 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_10 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_10 PRIVATE -Wall -Wextra)
add_executable(p1c05_11 class_template_friend.cpp)
set_target_properties(p1c05_11 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_11 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_11 PRIVATE -Wall -Wextra)
add_executable(p1c05_12 class_template_application.cpp)
set_target_properties(p1c05_12 PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED ON C_EXTENSIONS OFF)
set_target_properties(p1c05_12 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_compile_options(p1c05_12 PRIVATE -Wall -Wextra)
add_custom_target(all_p01_ch05 DEPENDS p1c05_01 p1c05_02 p1c05_03 p1c05_04 p1c05_05 p1c05_06 p1c05_07 p1c05_08 p1c05_09 p1c05_10 p1c05_11 p1c05_12)
+102
View File
@@ -0,0 +1,102 @@
// ============================================================================
// p1c05_12 — 5.8 类模板的应用
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
#include <string>
// --- 原文片段 [58954472:11] 5.8 类模板的应用 ---
#include <string>
using std::string;
template<class T>
class MyArray {
public:
explicit MyArray(int capacity) {
this->m_Capacity = capacity;
this->m_Size = 0;
// 如果T是对象,那么这个对象必须提供默认的构造函数
pAddress = new T[this->m_Capacity];
}
MyArray(const MyArray& arr) {
this->m_Capacity = arr.m_Capacity;
this->m_Size = arr.m_Size;
this->pAddress = new T[this->m_Capacity];
for (int i = 0; i < this->m_Size; i++) {
this->pAddress[i] = arr.pAddress[i];
}
}
T& operator[](int index) { return this->pAddress[index]; }
void Push_back(const T& val) {
if (this->m_Capacity == this->m_Size) return;
this->pAddress[this->m_Size] = val;
this->m_Size++;
}
void Pop_back() { if (this->m_Size > 0) this->m_Size--; }
int getSize() { return this->m_Size; }
~MyArray() {
if (this->pAddress != NULL) {
delete[] this->pAddress;
this->pAddress = NULL;
this->m_Capacity = 0;
this->m_Size = 0;
}
}
private:
T* pAddress;
int m_Capacity;
int m_Size;
};
class Person {
public:
Person() {}
Person(string name, int age) { this->mName = name; this->mAge = age; }
public:
string mName;
int mAge;
};
void PrintMyArrayInt(MyArray<int>& arr) {
for (int i = 0; i < arr.getSize(); i++) {
cout << arr[i] << " ";
}
cout << endl;
}
void PrintMyPerson(MyArray<Person>& personArr) {
for (int i = 0; i < personArr.getSize(); i++) {
cout << "姓名:" << personArr[i].mName << " 年龄:" << personArr[i].mAge << endl;
}
}
// --- 测试代码(原文为文件作用域裸语句,已包进 main 使其可编译运行)---
int main() {
MyArray<int> myArrayInt(10);
for (int i = 0; i < 9; i++) {
myArrayInt.Push_back(i);
}
myArrayInt.Push_back(100);
PrintMyArrayInt(myArrayInt);
MyArray<Person> myArrayPerson(10);
Person p1("德玛西亚", 30);
Person p2("提莫", 20);
Person p3("孙悟空", 18);
Person p4("赵信", 15);
Person p5("赵云", 24);
myArrayPerson.Push_back(p1);
myArrayPerson.Push_back(p2);
myArrayPerson.Push_back(p3);
myArrayPerson.Push_back(p4);
myArrayPerson.Push_back(p5);
PrintMyPerson(myArrayPerson);
return 0;
}
// --- main ---
+48
View File
@@ -0,0 +1,48 @@
// ============================================================================
// p1c05_06 — 5.7.2 类模板做函数参数
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
#include <cstdio>
static inline void pause() { printf("按回车键继续..."); (void)getchar(); }
// --- 原文片段 [58954472:5] 5.7.2 类模板做函数参数 ---
//类模板
template<class NameType, class AgeType>
class Person{
public:
Person(NameType name, AgeType age){
this->mName = name;
this->mAge = age;
}
void PrintPerson(){
cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
}
public:
NameType mName;
AgeType mAge;
};
//类模板做函数参数
void DoBussiness(Person<string,int>& p){
p.mAge += 20;
p.mName += "_vip";
p.PrintPerson();
}
int main(){
Person<string, int> p("John", 30);
DoBussiness(p);
pause();
return EXIT_SUCCESS;
}
// --- main ---
+42
View File
@@ -0,0 +1,42 @@
// ============================================================================
// p1c05_05 — 5.7.1 类模板基本概念
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
// --- 原文片段 [58954472:4] 5.7.1 类模板基本概念 ---
template<class NameType, class AgeType>
class Person
{
public:
Person(NameType name, AgeType age)
{
this->mName = name;
this->mAge = age;
}
void showPerson()
{
cout << "name: " << this->mName << " age: " << this->mAge << endl;
}
public:
NameType mName;
AgeType mAge;
};
void test01()
{
//Person P1("德玛西亚",18); // 类模板不能进行类型自动推导
Person<string, int>P1("德玛西亚", 18);
P1.showPerson();
}
// --- main ---
int main() {
test01();
return 0;
}
+40
View File
@@ -0,0 +1,40 @@
// ============================================================================
// p1c05_07 — 5.7.3 类模板派生普通类
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
// --- 原文片段 [58954472:6] 5.7.3 类模板派生普通类 ---
//类模板
template<class T>
class MyClass{
public:
MyClass(T property){
this->mProperty = property;
}
public:
T mProperty;
};
//子类实例化的时候需要具体化的父类,子类需要知道父类的具体类型是什么样的
//这样c++编译器才能知道给子类分配多少内存
//普通派生类
class SubClass : public MyClass<int>{
public:
SubClass(int b) : MyClass<int>(20){
this->mB = b;
}
public:
int mB;
};
// --- main ---
int main() {
return 0;
}
@@ -0,0 +1,35 @@
// ============================================================================
// p1c05_08 — 5.7.4 类模板派生类模板
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
// --- 原文片段 [58954472:7] 5.7.4 类模板派生类模板 ---
//父类类模板
template<class T>
class Base
{
T m;
};
template<class T >
class Child2 : public Base<double> //继承类模板的时候,必须要确定基类的大小
{
public:
T mParam;
};
void test02()
{
Child2<int> d2;
}
// --- main ---
int main() {
test02();
return 0;
}
+83
View File
@@ -0,0 +1,83 @@
// ============================================================================
// p1c05_11 — 5.7.7 模板类碰到友元函数
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
#include <cstdio>
static inline void pause() { printf("按回车键继续..."); (void)getchar(); }
// --- 原文片段 [58954472:10] 5.7.7 模板类碰到友元函数 ---
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include <string>
template<class T1, class T2> class Person;
//告诉编译器这个函数模板是存在
template<class T1, class T2> void PrintPerson2(Person<T1, T2>& p);
//友元函数在类内实现
template<class T1, class T2>
class Person{
//1. 友元函数在类内实现
friend void PrintPerson(Person<T1, T2>& p){
cout << "Name:" << p.mName << " Age:" << p.mAge << endl;
}
//2.友元函数类外实现
//告诉编译器这个函数模板是存在
friend void PrintPerson2<>(Person<T1, T2>& p);
//3. 类模板碰到友元函数模板
template<class U1, class U2>
friend void PrintPerson(Person<U1, U2>& p);
public:
Person(T1 name, T2 age){
this->mName = name;
this->mAge = age;
}
void showPerson(){
cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
}
private:
T1 mName;
T2 mAge;
};
void test01()
{
Person <string, int>p("Jerry", 20);
PrintPerson(p);
}
// 类模板碰到友元函数
//友元函数类外实现 加上<>空参数列表,告诉编译去匹配函数模板
template<class T1 , class T2>
void PrintPerson2(Person<T1, T2>& p)
{
cout << "Name2:" << p.mName << " Age2:" << p.mAge << endl;
}
void test02()
{
Person <string, int>p("Jerry", 20);
PrintPerson2(p); //不写可以编译通过,写了之后,会找PrintPerson2的普通函数调用,因为写了普通函数PrintPerson2的声明
}
int main(){
//test01();
test02();
pause();
return EXIT_SUCCESS;
}
// --- main ---
+42
View File
@@ -0,0 +1,42 @@
// ============================================================================
// p1c05_09 — 5.7.5 类模板类内实现
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
// --- 原文片段 [58954472:8] 5.7.5 类模板类内实现 ---
template<class NameType, class AgeType>
class Person
{
public:
Person(NameType name, AgeType age)
{
this->mName = name;
this->mAge = age;
}
void showPerson()
{
cout << "name: " << this->mName << " age: " << this->mAge << endl;
}
public:
NameType mName;
AgeType mAge;
};
void test01()
{
//Person P1("德玛西亚",18); // 类模板不能进行类型自动推导
Person<string, int>P1("德玛西亚", 18);
P1.showPerson();
}
// --- main ---
int main() {
test01();
return 0;
}
@@ -0,0 +1,60 @@
// ============================================================================
// p1c05_10 — 5.7.6 类模板类外实现
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
#include <cstdio>
static inline void pause() { printf("按回车键继续..."); (void)getchar(); }
// --- 原文片段 [58954472:9] 5.7.6 类模板类外实现 ---
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
template<class T1, class T2>
class Person{
public:
Person(T1 name, T2 age);
void showPerson();
public:
T1 mName;
T2 mAge;
};
//类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age){
this->mName = name;
this->mAge = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson(){
cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
}
void test()
{
Person<string, int> p("Obama", 20);
p.showPerson();
}
int main(){
test();
pause();
return EXIT_SUCCESS;
}
// --- main ---
+62
View File
@@ -0,0 +1,62 @@
// ============================================================================
// p1c05_01 — 5.2 函数模板
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
// --- 原文片段 [58954472:0] 5.2 函数模板 ---
//交换int数据
void SwapInt(int& a,int& b){
int temp = a;
a = b;
b = temp;
}
//交换char数据
void SwapChar(char& a,char& b){
char temp = a;
a = b;
b = temp;
}
//问题:如果我要交换double类型数据,那么还需要些一个double类型数据交换的函数
//繁琐,写的函数越多,当交换逻辑发生变化的时候,所有的函数都需要修改,无形当中增加了代码的维护难度
//如果能把类型作为参数传递进来就好了,传递int就是Int类型交换,传递char就是char类型交换
//我们有一种技术,可以实现类型的参数化---函数模板
//class 和 typename都是一样的,用哪个都可以
template<class T>
void MySwap(T& a,T& b){
T temp = a;
a = b;
b = temp;
}
void test01(){
int a = 10;
int b = 20;
cout << "a:" << a << " b:" << b << endl;
//1. 这里有个需要注意点,函数模板可以自动推导参数的类型
MySwap(a,b);
cout << "a:" << a << " b:" << b << endl;
char c1 = 'a';
char c2 = 'b';
cout << "c1:" << c1 << " c2:" << c2 << endl;
//2. 函数模板可以自动类型推导,那么也可以显式指定类型
MySwap<char>(c1, c2);
cout << "c1:" << c1 << " c2:" << c2 << endl;
}
// --- main ---
int main() {
test01();
return 0;
}
+62
View File
@@ -0,0 +1,62 @@
// ============================================================================
// p1c05_03 — 5.4 函数模板和普通函数在一起调用规则
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
// --- 原文片段 [58954472:2] 5.4 函数模板和普通函数在一起调用规则 ---
//函数模板
template<class T>
T MyPlus_1(T a, T b){
T ret = a + b;
return ret;
}
//普通函数
int MyPlus_1(int a, int b){
int ret = a + b;
return ret;
}
void test03(){
int a = 10;
int b = 20;
char c = 'a';
char d = 'b';
//如果函数模板和普通函数都能匹配,c++编译器优先考虑普通函数
cout << MyPlus_1(a, b) << endl;
//如果我必须要调用函数模板,那么怎么办?
cout << MyPlus_1<>(a, b) << endl;
//此时普通函数也可以匹配,因为普通函数可以自动类型转换
//但是此时函数模板能够有更好的匹配
//如果函数模板可以产生一个更好的匹配,那么选择模板
cout << MyPlus_1(c,d);
}
//函数模板重载
template<class T>
T MyPlus_1(T a, T b, T c){
T ret = a + b + c;
return ret;
}
void test04(){
int a = 10;
int b = 20;
int c = 30;
cout << MyPlus_1(a, b, c) << endl;
//如果函数模板和普通函数都能匹配,c++编译器优先考虑普通函数
}
// --- main ---
int main() {
test03();
test04();
return 0;
}
+66
View File
@@ -0,0 +1,66 @@
// ============================================================================
// p1c05_04 — 5.6模板的局限性
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
// --- 原文片段 [58954472:3] 5.6模板的局限性 ---
class Person
{
public:
Person(string name, int age)
{
this->mName = name;
this->mAge = age;
}
string mName;
int mAge;
};
//普通交换函数
template <class T>
void mySwap(T &a,T &b)
{
T temp = a;
a = b;
b = temp;
}
//第三代具体化,显示具体化的原型和定意思以template<>开头,并通过名称来指出类型
//具体化优先于常规模板
template<>void mySwap<Person>(Person &p1, Person &p2)
{
string nameTemp;
int ageTemp;
nameTemp = p1.mName;
p1.mName = p2.mName;
p2.mName = nameTemp;
ageTemp = p1.mAge;
p1.mAge = p2.mAge;
p2.mAge = ageTemp;
}
void test()
{
Person P1("Tom", 10);
Person P2("Jerry", 20);
cout << "P1 Name = " << P1.mName << " P1 Age = " << P1.mAge << endl;
cout << "P2 Name = " << P2.mName << " P2 Age = " << P2.mAge << endl;
mySwap(P1, P2);
cout << "P1 Name = " << P1.mName << " P1 Age = " << P1.mAge << endl;
cout << "P2 Name = " << P2.mName << " P2 Age = " << P2.mAge << endl;
}
// --- main ---
int main() {
test();
return 0;
}
+48
View File
@@ -0,0 +1,48 @@
// ============================================================================
// p1c05_02 — 5.3 函数模板和普通函数区别
// 来源:川大 C++/LinuxC wiki「02.Qt方向」
// 说明:本文件由 gen_part1.py 合并页面中的教学片段而成。每个片段用
// // --- 原文片段 [pageId:blockIdx] --- 标注出处。
// 已做最小修正(笔误/平台移植),详见 docs/ERRATA.md。
// ============================================================================
#include <iostream>
using namespace std;
// --- 原文片段 [58954472:1] 5.3 函数模板和普通函数区别 ---
//函数模板
template<class T>
T MyPlus_1(T a, T b){
T ret = a + b;
return ret;
}
//普通函数
int MyPlus_1(int a,char b){
int ret = a + b;
return ret;
}
void test02(){
int a = 10;
char b = 'a';
//调用函数模板,严格匹配类型
MyPlus_1(a, a);
MyPlus_1(b, b);
//调用普通函数
MyPlus_1(a, b);
//调用普通函数 普通函数可以隐式类型转换
MyPlus_1(b, a);
//结论:
//函数模板不允许自动类型转换,必须严格匹配类型
//普通函数可以进行自动类型转换
}
// --- main ---
int main() {
test02();
return 0;
}