13b3ebbe14
把川大 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 运行通过。
1 line
9.2 KiB
JSON
1 line
9.2 KiB
JSON
{"id":"58954448","type":"page","status":"current","title":"01.类和对象的基本概念","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/58954448/version/1"},"_expandable":{"content":"/rest/api/content/58954448"}},"body":{"storage":{"value":"<ac:layout><ac:layout-section ac:type=\"two_right_sidebar\"><ac:layout-cell><h3><span>4.1.1 C</span>和<span>C++</span>中<span>struct</span>区别</h3><ul><li>c语言<span>struct</span>只有变量</li><li>c++语言<span>struct </span>既有变量,也有函数</li></ul><h3><span>4.1.2 </span>类的封装</h3><p>我们编写程序的目的是为了解决现实中的问题,而这些问题的构成都是由各种事物组成,我们在计算机中要解决这种问题,首先要做就是要将这个问题的参与者:事和物抽象到计算机程序中,也就是用程序语言表示现实的事物。</p><p>那么现在问题是如何用程序语言来表示现实事物?现实世界的事物所具有的共性就是每个事物都具有自身的属性,一些自身具有的行为,所以如果我们能把事物的属性和行为表示出来,那么就可以抽象出来这个事物。</p><p>比如我们要表示人这个对象,在c语言中,我们可以这么表示:</p><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"89c06eba-e565-491c-86e1-97fb678c12e2\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[typedef struct _Person{\n\tchar name[64];\n\tint age;\n}Person;\ntypedef struct _Aninal{\n\tchar name[64];\n\tint age;\n\tint type; //动物种类\n}Ainmal;\n\nvoid PersonEat(Person* person){\n\tprintf(\"%s在吃人吃的饭!\\n\",person->name);\n}\nvoid AnimalEat(Ainmal* animal){\n\tprintf(\"%s在吃动物吃的饭!\\n\", animal->name);\n}\n\nint main(){\n\n\tPerson person;\n\tstrcpy(person.name, \"小明\");\n\tperson.age = 30;\n\tAnimalEat(&person);\n\n\treturn EXIT_SUCCESS;\n}]]></ac:plain-text-body></ac:structured-macro><p>定义一个结构体用来表示一个对象所包含的属性,函数用来表示一个对象所具有的行为,这样我们就表示出来一个事物,在c语言中,行为和属性是分开的,也就是说吃饭这个属性不属于某类对象,而属于所有的共同的数据,所以不单单是PeopleEat可以调用Person数据,AnimalEat也可以调用Person数据,那么万一调用错误,将会导致问题发生。</p><p>从这个案例我们应该可以体会到,属性和行为应该放在一起,一起表示一个具有属性和行为的对象。</p><p>假如某对象的某项属性不想被外界获知,比如说漂亮女孩的年龄不想被其他人知道,那么年龄这条属性应该作为女孩自己知道的属性;或者女孩的某些行为不想让外界知道,只需要自己知道就可以。那么这种情况下,封装应该再提供一种机制能够给属性和行为的访问权限控制住。</p><p>所以说封装特性包含两个方面,一个是属性和变量合成一个整体,一个是给属性和函数增加访问权限。</p><ul><li>封装</li></ul><ol><li>把变量(属性)和函数(操作)合成一个整体,封装在一个类中</li><li>对变量和函数进行访问控制</li></ol><ul><li>访问权限</li></ul><ol><li>在类的内部<span>(</span>作用域范围内<span>)</span>,没有访问权限之分,所有成员可以相互访问</li><li>在类的外部<span>(</span>作用域范围外<span>)</span>,访问权限才有意义:<span>public</span>,<span>private</span>,<span>protected</span></li><li>在类的外部,只有<span>public</span>修饰的成员才能被访问,在没有涉及继承与派生时,<span> private</span>和<span>protected</span>是同等级的,外部不允许访问</li></ol><p><span> </span></p><table><colgroup><col /><col /><col /><col /></colgroup><tbody><tr><th>访问属性</th><th>属性</th><th>对象内部</th><th>对象外部</th></tr><tr><td>public</td><td>公有</td><td>可访问</td><td>可访问</td></tr><tr><td>protected</td><td>保护</td><td>可访问</td><td>不可访问</td></tr><tr><td>private</td><td>私有</td><td>可访问</td><td>不可访问</td></tr></tbody></table><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"3a498986-7e37-4575-8ca3-100c18cafba6\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[//封装两层含义\n//1. 属性和行为合成一个整体\n//2. 访问控制,现实事物本身有些属性和行为是不对外开放\nclass Person{\n//人具有的行为(函数)\npublic:\n\tvoid Dese(){ cout << \"我有钱,年轻,个子又高,就爱嘚瑟!\" << endl;}\n//人的属性(变量)\npublic:\n\tint mTall; //多高,可以让外人知道\nprotected:\n\tint mMoney; // 有多少钱,只能儿子孙子知道\nprivate:\n\tint mAge; //年龄,不想让外人知道\n};\n\nint main(){\n\n\tPerson p;\n\tp.mTall = 220;\n\t//p.mMoney 保护成员外部无法访问\n\t//p.mAge 私有成员外部无法访问\n\tp.Dese();\n\n\treturn EXIT_SUCCESS;\n}]]></ac:plain-text-body></ac:structured-macro><p><span> </span></p><table><colgroup><col /></colgroup><tbody><tr><td><p> <strong>[struct</strong><strong>和<span>class</span>的区别<span>?]</span></strong></p><p><strong> </strong>class默认访问权限为<span>private,struct</span>默认访问权限为<span>public.</span></p></td></tr></tbody></table><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"537995b7-5b12-4e7b-bd2d-8f8aec6e704e\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[class A{\n\tint mAge;\n};\nstruct B{\n\tint mAge;\n};\n\nvoid test(){\n\tA a;\n\tB b;\n\t//a.mAge; //无法访问私有成员\n\tb.mAge; //可正常外部访问\n}]]></ac:plain-text-body></ac:structured-macro><h3><span>4.1.3 </span>将成员变量设置为<span>private</span></h3><ol><li>可赋予客户端访问数据的一致性。</li></ol><p>如果成员变量不是<span>public</span>,客户端唯一能够访问对象的方法就是通过成员函数。如果类中所有<span>public</span>权限的成员都是函数,客户在访问类成员时只会默认访问函数,不需要考虑访问的成员需不需要添加<span>(),</span>这就省下了许多搔首弄耳的时间。</p><ol><li>可细微划分访问控制。</li></ol><p>使用成员函数可使得我们对变量的控制处理更加精细。如果我们让所有的成员变量为<span>public</span>,每个人都可以读写它。如果我们设置为<span>private</span>,我们可以实现“不准访问”、“只读访问”、“读写访问”,甚至你可以写出“只写访问”。</p><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"d43d86c7-ebc2-476e-8c34-f927c5bf619d\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[class AccessLevels{\npublic:\n\t//对只读属性进行只读访问\n\tint getReadOnly(){ return readOnly; }\n\t//对读写属性进行读写访问\n\tvoid setReadWrite(int val){ readWrite = val; }\n\tint getReadWrite(){ return readWrite; }\n\t//对只写属性进行只写访问\n\tvoid setWriteOnly(int val){ writeOnly = val; }\nprivate:\n\tint readOnly; //对外只读访问\n\tint noAccess; //外部不可访问\n\tint readWrite; //读写访问\n\tint writeOnly; //只写访问\n};]]></ac:plain-text-body></ac:structured-macro><h3><span>4.1.4 </span>课堂练习</h3><table><colgroup><col /></colgroup><tbody><tr><td><p>请设计一个<span>Person</span>类,<span>Person</span>类具有<span>name</span>和<span>age</span>属性,提供初始化函数<span>(Init)</span>,并提供对<span>name</span>和<span>age</span>的读写函数<span>(set</span>,<span>get)</span>,但必须确保<span>age</span>的赋值在有效范围内<span>(0-100),</span>超出有效范围,则拒绝赋值,并提供方法输出姓名和年龄<span>.(10</span>分钟<span>)</span></p></td></tr></tbody></table></ac:layout-cell><ac:layout-cell><p><br /></p></ac:layout-cell></ac:layout-section></ac:layout>","representation":"storage","_expandable":{"content":"/rest/api/content/58954448"}},"_expandable":{"editor":"","view":"","export_view":"","styled_view":"","anonymous_export_view":""}},"extensions":{"position":"none"},"_links":{"webui":"/pages/viewpage.action?pageId=58954448","edit":"/pages/resumedraft.action?draftId=58954448","tinyui":"/x/0JKDAw","collection":"/rest/api/content","base":"https://wiki.suncaper.net","context":"","self":"https://wiki.suncaper.net/rest/api/content/58954448"},"_expandable":{"container":"/rest/api/space/2CT","metadata":"","operations":"","children":"/rest/api/content/58954448/child","restrictions":"/rest/api/content/58954448/restriction/byOperation","history":"/rest/api/content/58954448/history","ancestors":"","descendants":"/rest/api/content/58954448/descendant","space":"/rest/api/space/2CT"}} |