Files
scuc-qt-course/tools/wiki_data/bodies/58954472.json
T
张宗平 13b3ebbe14 课程代码仓库初始化: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 运行通过。
2026-06-30 14:16:55 +08:00

1 line
20 KiB
JSON
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"id":"58954472","type":"page","status":"current","title":"05.C++模板","version":{"by":{"type":"known","username":"ethanliu","userKey":"2c90931b6cfb654f016d5c69becc0001","profilePicture":{"path":"/images/icons/profilepics/default.svg","width":48,"height":48,"isDefault":true},"displayName":"刘浩","_links":{"self":"https://wiki.suncaper.net/rest/api/user?key=2c90931b6cfb654f016d5c69becc0001"},"_expandable":{"status":""}},"when":"2022-07-09T01:51:24.000Z","message":"","number":1,"minorEdit":false,"hidden":false,"_links":{"self":"https://wiki.suncaper.net/rest/experimental/content/58954472/version/1"},"_expandable":{"content":"/rest/api/content/58954472"}},"body":{"storage":{"value":"<ac:layout><ac:layout-section ac:type=\"two_right_sidebar\"><ac:layout-cell><h2><span>5.1 </span>模板概论</h2><p>c++提供了函数模板<span>(function template.)</span>所谓函数模板,<strong>实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来代表。这个通用函数就成为函数模板。</strong>凡是函数体相同的函数都可以用这个模板代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现不同函数的功能。</p><ul><li>c++提供两种模板机制<span>:</span><strong>函数模板</strong>和<strong>类模板</strong></li><li>类属<span> - </span>类型参数化,又称参数模板</li></ul><p><strong>总结:</strong></p><ul><li>模板把函数或类要处理的数据类型参数化,表现为参数的多态性,成为类属。</li><li>模板用于表达逻辑结构相同,但具体数据元素类型不同的数据对象的通用行为。</li></ul><h2><span>5.2 </span>函数模板</h2><p>5.2.1 什么是函数模板?</p><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"b29ed2e8-d205-4409-bba4-3e596b20464b\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[//交换int数据\nvoid SwapInt(int& a,int& b){\n\tint temp = a;\n\ta = b;\n\tb = temp;\n}\n\n//交换char数据\nvoid SwapChar(char& a,char& b){\n\tchar temp = a;\n\ta = b;\n\tb = temp;\n}\n//问题:如果我要交换double类型数据,那么还需要些一个double类型数据交换的函数\n//繁琐,写的函数越多,当交换逻辑发生变化的时候,所有的函数都需要修改,无形当中增加了代码的维护难度\n\n//如果能把类型作为参数传递进来就好了,传递int就是Int类型交换,传递char就是char类型交换\n//我们有一种技术,可以实现类型的参数化---函数模板\n\n\n//class 和 typename都是一样的,用哪个都可以\ntemplate<class T>\nvoid MySwap(T& a,T& b){\n\tT temp = a;\n\ta = b;\n\tb = temp;\n}\n\nvoid test01(){\n\t\n\tint a = 10;\n\tint b = 20;\n\tcout << \"a:\" << a << \" b:\" << b << endl;\n\t//1. 这里有个需要注意点,函数模板可以自动推导参数的类型\n\tMySwap(a,b);\n\tcout << \"a:\" << a << \" b:\" << b << endl;\n\n\tchar c1 = 'a';\n\tchar c2 = 'b';\n\tcout << \"c1:\" << c1 << \" c2:\" << c2 << endl;\n\t//2. 函数模板可以自动类型推导,那么也可以显式指定类型\n\tMySwap<char>(c1, c2);\n\tcout << \"c1:\" << c1 << \" c2:\" << c2 << endl;\n}]]></ac:plain-text-body></ac:structured-macro><p>5.2.2 课堂练习</p><table><colgroup><col /></colgroup><tbody><tr><td><p><strong>使用函数模板实现对</strong><strong>char</strong><strong>和<span>int</span>类型数组进行排序?</strong></p></td></tr></tbody></table><h2><span>5.3 </span>函数模板和普通函数区别</h2><ul><li>函数模板不允许自动类型转化</li><li>普通函数能够自动进行类型转化</li></ul><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"30721a88-0a46-4e7c-a7c0-e05be4cb6e96\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[//函数模板\ntemplate<class T>\nT MyPlus(T a, T b){\n\tT ret = a + b;\n\treturn ret;\n}\n\n//普通函数\nint MyPlus(int a,char b){\n\tint ret = a + b;\n\treturn ret;\n}\n\nvoid test02(){\n\n\tint a = 10;\n\tchar b = 'a';\n\n\t//调用函数模板,严格匹配类型\n\tMyPlus(a, a);\n\tMyPlus(b, b);\n\t//调用普通函数\n\tMyPlus(a, b);\n\t//调用普通函数 普通函数可以隐式类型转换\n\tMyPlus(b, a);\n\n\t//结论:\n\t//函数模板不允许自动类型转换,必须严格匹配类型\n\t//普通函数可以进行自动类型转换\n}]]></ac:plain-text-body></ac:structured-macro><h2><span>5.4 </span>函数模板和普通函数在一起调用规则</h2><ul><li>c++编译器优先考虑普通函数</li><li>可以通过空模板实参列表的语法限定编译器只能通过模板匹配</li><li>函数模板可以像普通函数那样可以被重载</li><li>如果函数模板可以产生一个更好的匹配,那么选择模板</li></ul><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"f93bd0d8-fbf6-4b07-bbea-10d1ec784a58\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[//函数模板\ntemplate<class T>\nT MyPlus(T a, T b){\n\tT ret = a + b;\n\treturn ret;\n}\n\n//普通函数\nint MyPlus(int a, int b){\n\tint ret = a + b;\n\treturn ret;\n}\n\nvoid test03(){\n\tint a = 10;\n\tint b = 20;\n\tchar c = 'a';\n\tchar d = 'b';\n\t//如果函数模板和普通函数都能匹配,c++编译器优先考虑普通函数\n\tcout << MyPlus(a, b) << endl;\n\t//如果我必须要调用函数模板,那么怎么办?\n\tcout << MyPlus<>(a, b) << endl;\n\t//此时普通函数也可以匹配,因为普通函数可以自动类型转换\n\t//但是此时函数模板能够有更好的匹配\n\t//如果函数模板可以产生一个更好的匹配,那么选择模板\n\tcout << MyPlus(c,d);\n}\n\n//函数模板重载\ntemplate<class T>\nT MyPlus(T a, T b, T c){\n\tT ret = a + b + c;\n\treturn ret;\n}\n\nvoid test04(){\n\n\tint a = 10;\n\tint b = 20;\n\tint c = 30;\n\tcout << MyPlus(a, b, c) << endl;\n\t//如果函数模板和普通函数都能匹配,c++编译器优先考虑普通函数\n}]]></ac:plain-text-body></ac:structured-macro><h2><span>5.5 </span>模板机制剖析</h2><p><strong>思考<span>:</span>为什么函数模板可以和普通函数放在一起<span>?c++</span>编译器是如何实现函数模板机制的?</strong></p><h3><span>5.5.1</span>编译过程</h3><p>hello.cpp程序是高级<span>c</span>语言程序,这种程序易于被人读懂。为了在系统上运行<span>hello.c</span>程序,每一条<span>c</span>语句都必须转化为低级的机器指令。然后将这些机器指令打包成可执行目标文件格式,并以二进制形式存储于磁盘中。</p><p>预处理<span>(Pre-processing) -&gt; </span>编译<span>(Compiling) -&gt;</span>汇编<span>(Assembling) -&gt; </span>链接<span>(Linking)</span></p><h3><span>5.5.2 </span>模板实现机制</h3><p><strong>函数模板机制结论:</strong></p><ul><li><strong>编译器并不是把函数模板处理成能够处理任何类型的函数</strong></li><li><strong>函数模板通过具体类型产生不同的函数</strong></li><li><strong>编译器会对函数模板进行两次编译,在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译。</strong></li></ul><h2><span>5.6</span>模板的局限性</h2><p><strong>假设有如下模板函数:</strong></p><p><strong>       template&lt;class T&gt;</strong></p><p><strong>       void f(T a, T b)</strong></p><p><strong>       { … }</strong></p><p><strong>如果代码实现时定义了赋值操作<span> a = b</span>,但是<span>T</span>为数组,这种假设就不成立了</strong></p><p><strong>同样,如果里面的语句为判断语句<span> if(a&gt;b),</span>但<span>T</span>如果是结构体,该假设也不成立,另外如果是传入的数组,数组名为地址,因此它比较的是地址,而这也不是我们所希望的操作。</strong></p><p><strong>       总之,编写的模板函数很可能无法处理某些类型,另一方面,有时候通用化是有意义的,但<span>C++</span>语法不允许这样做。为了解决这种问题,可以提供模板的重载,为这些特定的类型提供具体化的模板。</strong></p><p><br /></p><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"daed97d5-397e-4996-a961-d1e222c265fa\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[class Person\n{\npublic:\n\tPerson(string name, int age)\n\t{\n\t\tthis->mName = name;\n\t\tthis->mAge = age;\n\t}\n\tstring mName;\n\tint mAge;\n};\n\n//普通交换函数\ntemplate <class T>\nvoid mySwap(T &a,T &b)\n{\n\tT temp = a;\n\ta = b; \n\tb = temp;\n}\n//第三代具体化,显示具体化的原型和定意思以template<>开头,并通过名称来指出类型\n//具体化优先于常规模板\ntemplate<>void mySwap<Person>(Person &p1, Person &p2)\n{\n\tstring nameTemp;\n\tint ageTemp;\n\n\tnameTemp = p1.mName;\n\tp1.mName = p2.mName;\n\tp2.mName = nameTemp;\n\n\tageTemp = p1.mAge;\n\tp1.mAge = p2.mAge;\n\tp2.mAge = ageTemp;\n\n}\n\nvoid test()\n{\n\tPerson P1(\"Tom\", 10);\n\tPerson P2(\"Jerry\", 20);\n\n\tcout << \"P1 Name = \" << P1.mName << \" P1 Age = \" << P1.mAge << endl;\n\tcout << \"P2 Name = \" << P2.mName << \" P2 Age = \" << P2.mAge << endl;\n\tmySwap(P1, P2);\n\tcout << \"P1 Name = \" << P1.mName << \" P1 Age = \" << P1.mAge << endl;\n\tcout << \"P2 Name = \" << P2.mName << \" P2 Age = \" << P2.mAge << endl;\n}\n\n]]></ac:plain-text-body></ac:structured-macro><p><br /></p><h2><span>5.7 </span>类模板</h2><h3><span>5.7.1 </span>类模板基本概念</h3><p>类模板和函数模板的定义和使用类似,我们已经进行了介绍。有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同。</p><ul><li>类模板用于实现类所需数据的类型参数化</li></ul><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"973a517e-5c9b-4f70-a623-64e82be1ec91\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[template<class NameType, class AgeType>\nclass Person\n{\npublic:\n\tPerson(NameType name, AgeType age)\n\t{\n\t\tthis->mName = name;\n\t\tthis->mAge = age;\n\t}\n\tvoid showPerson()\n\t{\n\t\tcout << \"name: \" << this->mName << \" age: \" << this->mAge << endl;\n\t}\npublic:\n\tNameType mName;\n\tAgeType mAge;\n};\n\nvoid test01()\n{\n\t//Person P1(\"德玛西亚\",18); // 类模板不能进行类型自动推导 \n\tPerson<string, int>P1(\"德玛西亚\", 18);\n\tP1.showPerson();\n}]]></ac:plain-text-body></ac:structured-macro><h3><span>5.7.2 </span>类模板做函数参数</h3><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"dee49617-93ce-4943-bcc9-e98555da31b9\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[//类模板\ntemplate<class NameType, class AgeType>\nclass Person{\npublic:\n\tPerson(NameType name, AgeType age){\n\t\tthis->mName = name;\n\t\tthis->mAge = age;\n\t}\n\tvoid PrintPerson(){\n\t\tcout << \"Name:\" << this->mName << \" Age:\" << this->mAge << endl;\n\t}\npublic:\n\tNameType mName;\n\tAgeType mAge;\n};\n\n//类模板做函数参数\nvoid DoBussiness(Person<string,int>& p){\n\tp.mAge += 20;\n\tp.mName += \"_vip\";\n\tp.PrintPerson();\n}\n\nint main(){\n\n\tPerson<string, int> p(\"John\", 30);\n\tDoBussiness(p);\n\n\tsystem(\"pause\");\n\treturn EXIT_SUCCESS;\n}]]></ac:plain-text-body></ac:structured-macro><h3><span>5.7.3 </span>类模板派生普通类</h3><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"cddc0b6d-bd86-4b13-8736-b71a2a4dea59\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[//类模板\ntemplate<class T>\nclass MyClass{\npublic:\n\tMyClass(T property){\n\t\tthis->mProperty = property;\n\t}\npublic:\n\tT mProperty;\n};\n\n//子类实例化的时候需要具体化的父类,子类需要知道父类的具体类型是什么样的\n//这样c++编译器才能知道给子类分配多少内存\n\n//普通派生类\nclass SubClass : public MyClass<int>{\npublic:\n\tSubClass(int b) : MyClass<int>(20){\n\t\tthis->mB = b;\n\t}\npublic:\n\tint mB;\n};]]></ac:plain-text-body></ac:structured-macro><h3><span>5.7.4 </span>类模板派生类模板</h3><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"388a2946-e912-4c78-a255-92bfa657c0d2\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[//父类类模板\ntemplate<class T>\nclass Base\n{\n\tT m;\n};\ntemplate<class T >\nclass Child2 : public Base<double> //继承类模板的时候,必须要确定基类的大小\n{\npublic:\n\tT mParam;\n};\n\nvoid test02()\n{\n\tChild2<int> d2;\n}]]></ac:plain-text-body></ac:structured-macro><h3><span>5.7.5 </span>类模板类内实现</h3><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"160621e1-7831-4bab-9d2c-a73ad8b2f1cd\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[template<class NameType, class AgeType>\nclass Person\n{\npublic:\n\tPerson(NameType name, AgeType age)\n\t{\n\t\tthis->mName = name;\n\t\tthis->mAge = age;\n\t}\n\tvoid showPerson()\n\t{\n\t\tcout << \"name: \" << this->mName << \" age: \" << this->mAge << endl;\n\t}\npublic:\n\tNameType mName;\n\tAgeType mAge;\n};\n\nvoid test01()\n{\n\t//Person P1(\"德玛西亚\",18); // 类模板不能进行类型自动推导 \n\tPerson<string, int>P1(\"德玛西亚\", 18);\n\tP1.showPerson();\n}]]></ac:plain-text-body></ac:structured-macro><h3><span>5.7.6 </span>类模板类外实现</h3><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"246496ff-3ca0-4180-a3f8-9d3f6d19b73e\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[#define _CRT_SECURE_NO_WARNINGS\n#include<iostream>\n#include<string>\nusing namespace std;\n\ntemplate<class T1, class T2>\nclass Person{\npublic:\n\tPerson(T1 name, T2 age);\n\tvoid showPerson();\n\npublic:\n\tT1 mName;\n\tT2 mAge;\n};\n\n\n//类外实现\ntemplate<class T1, class T2>\nPerson<T1, T2>::Person(T1 name, T2 age){\n\tthis->mName = name;\n\tthis->mAge = age;\n}\n\n\ntemplate<class T1, class T2>\nvoid Person<T1, T2>::showPerson(){\n\tcout << \"Name:\" << this->mName << \" Age:\" << this->mAge << endl;\n}\n\nvoid test()\n{\n\tPerson<string, int> p(\"Obama\", 20);\n\tp.showPerson();\n}\n\nint main(){\n\n\ttest();\n\n\tsystem(\"pause\");\n\treturn EXIT_SUCCESS;\n}]]></ac:plain-text-body></ac:structured-macro><h3>5.7.7    模板类碰到友元函数</h3><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"10b7ef90-43f7-4c5f-820d-d379c524fd06\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[#define _CRT_SECURE_NO_WARNINGS\n#include<iostream>\nusing namespace std;\n#include <string>\n\ntemplate<class T1, class T2> class Person;\n//告诉编译器这个函数模板是存在\ntemplate<class T1, class T2> void PrintPerson2(Person<T1, T2>& p);\n\n//友元函数在类内实现\ntemplate<class T1, class T2>\nclass Person{\n\t//1. 友元函数在类内实现\n\tfriend void PrintPerson(Person<T1, T2>& p){\n\t\tcout << \"Name:\" << p.mName << \" Age:\" << p.mAge << endl;\n\t}\n\n\t//2.友元函数类外实现\n\t//告诉编译器这个函数模板是存在\n\tfriend void PrintPerson2<>(Person<T1, T2>& p);\n\n\t//3. 类模板碰到友元函数模板\n\ttemplate<class U1, class U2>\n\tfriend void PrintPerson(Person<U1, U2>& p);\n\npublic:\n\tPerson(T1 name, T2 age){\n\t\tthis->mName = name;\n\t\tthis->mAge = age;\n\t}\n\tvoid showPerson(){\n\t\tcout << \"Name:\" << this->mName << \" Age:\" << this->mAge << endl;\n\t}\nprivate:\n\tT1 mName;\n\tT2 mAge;\n};\n\nvoid test01()\n{\n\tPerson <string, int>p(\"Jerry\", 20);\n\tPrintPerson(p);\n}\n\n\n// 类模板碰到友元函数\n//友元函数类外实现 加上<>空参数列表,告诉编译去匹配函数模板\ntemplate<class T1 , class T2>\nvoid PrintPerson2(Person<T1, T2>& p)\n{\n\tcout << \"Name2:\" << p.mName << \" Age2:\" << p.mAge << endl;\n}\n\nvoid test02()\n{\n\tPerson <string, int>p(\"Jerry\", 20);\n\tPrintPerson2(p); //不写可以编译通过,写了之后,会找PrintPerson2的普通函数调用,因为写了普通函数PrintPerson2的声明\t\n}\n\nint main(){\n\n\t//test01();\n\ttest02();\n\tsystem(\"pause\");\n\treturn EXIT_SUCCESS;\n}]]></ac:plain-text-body></ac:structured-macro><h2>5.8         类模板的应用</h2><p>设计一个数组模板类<span>(MyArray),</span>完成对不同类型元素的管理</p><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"3704f744-e554-4557-bb70-ed76e05c5b9e\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[#pragma once\ntemplate<class T>\nclass MyArray\n{\npublic:\n\texplicit MyArray(int capacity)\n\t{\n\t\tthis->m_Capacity = capacity;\n\t\tthis->m_Size = 0;\n\t\t// 如果T是对象,那么这个对象必须提供默认的构造函数\n\t\tpAddress = new T[this->m_Capacity];\n\t}\n\n\t//拷贝构造\n\tMyArray(const MyArray & arr)\n\t{\n\t\tthis->m_Capacity = arr.m_Capacity;\n\t\tthis->m_Size = arr.m_Size;\n\t\tthis->pAddress = new T[this->m_Capacity];\n\t\tfor (int i = 0; i < this->m_Size;i++)\n\t\t{\n\t\t\tthis->pAddress[i] = arr.pAddress[i];\n\t\t}\n\t}\n\n\t//重载[] 操作符 arr[0]\n\tT& operator [](int index)\n\t{\n\t\treturn this->pAddress[index]; \n\t}\n\t//尾插法\n\tvoid Push_back(const T & val)\n\t{\n\t\tif (this->m_Capacity == this->m_Size)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tthis->pAddress[this->m_Size] = val;\n\t\tthis->m_Size++;\n\t}\n\tvoid Pop_back()\n\t{\n\t\tif (this->m_Size == 0)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tthis->m_Size--;\n\t}\n\tint\tgetSize()\n\t{\n\t\treturn this->m_Size;\n\t}\n\t//析构\n\t~MyArray()\n\t{\n\t\tif (this->pAddress != NULL)\n\t\t{\n\t\t\tdelete[] this->pAddress;\n\t\t\tthis->pAddress = NULL;\n\t\t\tthis->m_Capacity = 0; \n\t\t\tthis->m_Size = 0;\n\t\t}\n\t}\n\nprivate:\n\tT * pAddress; //指向一个堆空间,这个空间存储真正的数据\n\tint m_Capacity; //容量\n\tint m_Size; // 大小\n};\n\n测试代码:\n\n\nclass Person{\npublic:\n\tPerson(){}\n\tPerson(string name, int age){\n\t\tthis->mName = name;\n\t\tthis->mAge = age;\n\t}\npublic:\n\tstring mName;\n\tint mAge;\n};\n\n\nvoid PrintMyArrayInt(MyArray<int>& arr){\n\tfor (int i = 0; i < arr.getSize(); i++){\n\t\tcout << arr[i] << \" \";\n\t}\n\tcout << endl;\n}\n\nvoid PrintMyPerson(MyArray<Person>& personArr)\n{\n\tfor (int i = 0; i < personArr.getSize(); i++){\n\t\tcout << \"姓名:\" << personArr[i].mName << \" 年龄: \" << personArr[i].mAge << endl;\n\t}\n\t\n}\n\t\n\tMyArray<int> myArrayInt(10);\n\tfor (int i = 0; i < 9; i++)\n\t{\n\t\tmyArrayInt.Push_back(i);\n\t}\n\tmyArrayInt.Push_back(100);\n\tPrintMyArrayInt(myArrayInt);\n\nMyArray<Person> myArrayPerson(10);\n\tPerson p1(\"德玛西亚\", 30);\n\tPerson p2(\"提莫\", 20);\n\tPerson p3(\"孙悟空\",18);\n\tPerson p4(\"赵信\", 15);\n\tPerson p5(\"赵云\", 24);\n\tmyArrayPerson.Push_back(p1);\n\tmyArrayPerson.Push_back(p2);\n\tmyArrayPerson.Push_back(p3);\n\tmyArrayPerson.Push_back(p4);\n\tmyArrayPerson.Push_back(p5);]]></ac:plain-text-body></ac:structured-macro><p><br /></p><p><br /></p></ac:layout-cell><ac:layout-cell><p><br /></p></ac:layout-cell></ac:layout-section></ac:layout>","representation":"storage","_expandable":{"content":"/rest/api/content/58954472"}},"_expandable":{"editor":"","view":"","export_view":"","styled_view":"","anonymous_export_view":""}},"extensions":{"position":"none"},"_links":{"webui":"/pages/viewpage.action?pageId=58954472","edit":"/pages/resumedraft.action?draftId=58954472","tinyui":"/x/6JKDAw","collection":"/rest/api/content","base":"https://wiki.suncaper.net","context":"","self":"https://wiki.suncaper.net/rest/api/content/58954472"},"_expandable":{"container":"/rest/api/space/2CT","metadata":"","operations":"","children":"/rest/api/content/58954472/child","restrictions":"/rest/api/content/58954472/restriction/byOperation","history":"/rest/api/content/58954472/history","ancestors":"","descendants":"/rest/api/content/58954472/descendant","space":"/rest/api/space/2CT"}}