![基礎(chǔ)知識(shí)CPrimer全部深入對(duì)象模型前四章STL源碼剖析和指_第1頁(yè)](http://file4.renrendoc.com/view/44d0e41bfb9b044a91d4839e4d82ef81/44d0e41bfb9b044a91d4839e4d82ef811.gif)
![基礎(chǔ)知識(shí)CPrimer全部深入對(duì)象模型前四章STL源碼剖析和指_第2頁(yè)](http://file4.renrendoc.com/view/44d0e41bfb9b044a91d4839e4d82ef81/44d0e41bfb9b044a91d4839e4d82ef812.gif)
![基礎(chǔ)知識(shí)CPrimer全部深入對(duì)象模型前四章STL源碼剖析和指_第3頁(yè)](http://file4.renrendoc.com/view/44d0e41bfb9b044a91d4839e4d82ef81/44d0e41bfb9b044a91d4839e4d82ef813.gif)
![基礎(chǔ)知識(shí)CPrimer全部深入對(duì)象模型前四章STL源碼剖析和指_第4頁(yè)](http://file4.renrendoc.com/view/44d0e41bfb9b044a91d4839e4d82ef81/44d0e41bfb9b044a91d4839e4d82ef814.gif)
![基礎(chǔ)知識(shí)CPrimer全部深入對(duì)象模型前四章STL源碼剖析和指_第5頁(yè)](http://file4.renrendoc.com/view/44d0e41bfb9b044a91d4839e4d82ef81/44d0e41bfb9b044a91d4839e4d82ef815.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、C+ Primer(全部) 深入 C+對(duì)象模型(前四章)STL 源碼剖析(前四章)C 和指針 C 陷阱和缺陷(全部) 321C+C+編譯過(guò)程高級(jí)語(yǔ)言程序編譯的過(guò)程:預(yù)處理、編譯、匯編、1.1。預(yù)處理:頭文件的包含、宏定義的擴(kuò)展、條件編譯的選擇編譯:把源代碼翻譯成中間語(yǔ)言,即匯編語(yǔ)言匯編:把匯編代碼翻譯成機(jī)器代碼,即目標(biāo)代碼:找到所要用到函數(shù)所在的目標(biāo)文件,并頭文件在一起為可執(zhí)行文件1.2頭文件中的編譯宏” #ifndef INCvxWorksh、#define INCvxWorksh、#endif” 的作用是防止該頭文件被重復(fù)#include filename.h 與。#include 不同?
2、#include 在系統(tǒng)定義的頭文件路徑內(nèi)(包括命令行中用參數(shù)設(shè)置的包含路徑)搜索頭文件;#include filename.h在當(dāng)前路徑內(nèi)搜索頭文件。extern 關(guān)鍵字1.3extern 變量。作用是變量和函數(shù)為外部,即該變量或函數(shù)名在其它文件中可見(jiàn)。externx;只不定義,但是如果初始化的話就是定義了,比如 externy= 3。externx,y;告訴編譯器其后的變量已經(jīng)在別的文件中說(shuō)明,不再為它們分配內(nèi)存。 (可以多處,但是定義只能有一處)通常,在模塊的頭文件中對(duì)本模塊提供給其它模塊的函數(shù)和全局變量以關(guān)鍵字 extern。(沒(méi) extern,想用其他頭文件的全局變量全局函數(shù)就得 i
3、nclude 那個(gè)頭文件;不想 inlcude 的話就得在本文件內(nèi)使用 extern一下這個(gè)變量已經(jīng)在其他地方定義了)真理:只在頭文件中做而不定義舉例:test1.h全局變量 strvoid fun1();extern char str; /test1.cpp#include”test1.h” char str = “123456”;/定義全局變量 str void fun1()coutstrendl;test2.cpp#include”test1.h” void fun2() coutstrendl; test2.cpp 只要包含了 test1.h 文件就可以使用 str。但是如果把 str
4、 的定義放在頭文件 test1.h 的話,這里 test1.cpp 和 test2.cpp 都包含了test1.h 在編譯的時(shí)候會(huì)導(dǎo)致多沖定義錯(cuò)誤。換案:把 str 的定義從 test1.cpp 挪到 test1.h 中: extern char str = “123456”然后在 test2.cpp 中去掉#include “test1.h“ 然后加上extern char str;這樣 fun2 同樣可以運(yùn)行,以及不會(huì)編譯錯(cuò)誤。但是這樣的話,test1.h 中的 fun1 函數(shù)就無(wú)法使用了! extern 函數(shù) 同上extern C 在 C+環(huán)境下使用 C 函數(shù)的時(shí)候,常常會(huì)出現(xiàn)編譯器無(wú)法
5、找到 obj 模塊中的C 函數(shù)定義,從而導(dǎo)致失敗的情況。x,y ); C+編譯器會(huì)產(chǎn)生像_foo_之類的名字,實(shí)現(xiàn)函數(shù)重載,解void foo(決了函數(shù)的多態(tài)問(wèn)題。而 C 語(yǔ)言不會(huì),C 編譯器編譯后在符號(hào)庫(kù)中的名字為_(kāi)foo。因此會(huì)造成時(shí)找不到對(duì)應(yīng)函數(shù)的情況。extern C修飾的變量和函數(shù)是按照 C 語(yǔ)言方式編譯和連接的。extern C的目的是實(shí)現(xiàn) C+與 C 及其它語(yǔ)言的混合編程。C+調(diào)用 C 模塊C 語(yǔ)言頭文件 cExle.h externadd(x,y);le.hC 語(yǔ)言實(shí)現(xiàn)文件 cExle.c #include cExadd(x,y )C+實(shí)現(xiàn)文件 cppFile.cpp exte
6、rn C #include cExC 調(diào)用 C+模塊le.hmain()add(2,3);C+頭文件 cppExle.h extern Cadd(x,y );le.hC+實(shí)現(xiàn)文件 cppExle.cpp #include cppExadd(x,y)C 實(shí)現(xiàn)文件 cFile.c extern注意:C 語(yǔ)言中不能直接中定義的 extern C函數(shù)add(x,y );main()add(2,3);了 extern C的該頭文件,應(yīng)該僅在 C 文件中將 C+為 extern 類型。n; 另一個(gè)文件定義 long n;編譯器不一定能報(bào)錯(cuò)。PS:一個(gè)文件extern運(yùn)行時(shí)會(huì)發(fā)生的情況:1、編譯出錯(cuò) 2、l
7、ong 和起使用 4、出錯(cuò)了sic 關(guān)鍵字長(zhǎng)短一樣 3、兩個(gè)類型恰好可以一1.4sic 修飾的變量和函數(shù)都只限定于本文件使用。sic 修飾的全局變量與定義同時(shí)進(jìn)行。Extern 和 sic 不能同時(shí)修飾一個(gè)變量。靜態(tài)函數(shù)會(huì)被自動(dòng)分配在一個(gè)一直使用的區(qū),直到退出應(yīng)用程序?qū)嵗?,避免了調(diào)用函數(shù)時(shí)壓棧出棧,速度快很多。1、 sic 變量1).局部 a.靜態(tài)局部變量在函數(shù)內(nèi)定義,生存期為整個(gè)源程序,但作用域與自動(dòng)變量相同,只能在定義該變量的函數(shù)內(nèi)使用。退出該函數(shù)后,盡管該變量還繼續(xù)存在,但不能使用它。b.對(duì)基本類型的靜態(tài)局部變量若在說(shuō)明時(shí)未賦以初值,則系統(tǒng)自動(dòng)賦予 0 值。而對(duì)自動(dòng)變量不賦初值,則其值是
8、不定的。2).全局全局變量本身就是靜態(tài)方式, 靜態(tài)全局變量當(dāng)然也是靜態(tài)方式。但是他們的作用域,非靜態(tài)全局 變量的作用域是整個(gè)源程序(多個(gè)源文件可以共同使用); 而靜態(tài)全局變量則限制了其作用域, 即只在定義該變量的源文件內(nèi)有效, 在同一源程序的其它源文件中不能使用它。2、 sic 函數(shù)(也叫函數(shù))只能被本文件中的函數(shù)調(diào)用,而不能被同一程序其它文件中的函數(shù)調(diào)用。區(qū)別于一般的非靜態(tài)函數(shù)(外部函數(shù))Const 關(guān)鍵字全局作用域定義非 const 變量,默認(rèn)為 extern,整個(gè)程序都可以問(wèn),但是又不想 include 該文件的話,就要加一個(gè) extern 該變量)1.5(別的文件想要訪但是全局作用域定
9、義的 const 變量,具有 sic 特性,則只有本文件可以使用。但是const 可以與extern 連用來(lái)該常量可以作用于其他編譯模塊。F 1.cFile2.cextern constextern constt = 4;t;/這樣之后,后面才能使用 t 變量但是如果 file2.c 在 file1.c 之前編譯的話,就出錯(cuò)了!定義一個(gè)宏,比較兩個(gè)數(shù) a、b 的大小,不能使用大于、小于、if 語(yǔ)句#define max(a,b) (a)-(b)&(1 ()自左向右優(yōu)先級(jí)1.8單目次之:! + - - (type) * & sizeof自右向左 比方說(shuō)*p()的意思是*(p()雙目再次之:算術(shù)、
10、移位、關(guān)系、邏輯 從左到右三目:條件運(yùn)算符,右到左賦值運(yùn)算符再再再次之:(從右到左)最低的就是逗號(hào)了,從左到右注:=和!=優(yōu)先級(jí)要低于其他關(guān)系運(yùn)算符的優(yōu)先級(jí) ab = cd以及邏輯運(yùn)算符優(yōu)先級(jí)中 &高于高于|高于&高于| C+內(nèi)存管理代碼段:保存代碼堆棧段數(shù)據(jù)段:保存全局?jǐn)?shù)據(jù)和靜態(tài)數(shù)據(jù)1.9char str1 = abc; char str2 = abc;const char str3 = abc; const char str4 = abc; const char* str5 = abc; const char* str6 = abc; cout boolalpha ( str1=str2
11、) endl; / false cout boolalpha ( str3=str4 ) endl; / false cout boolalpha ( str5=str6 ) 數(shù)組 ajp+-指向數(shù)組 a0=數(shù)組 a1pi指針數(shù)組 aipijpi偏移 j所指元素?cái)?shù)組元素 aij*p指針 p0數(shù)組 a0*p指針 p0所指元素?cái)?shù)組元素 a00main 函數(shù)的 EBX,ESI,EDI 出棧ESP 指向 EBP 所指的內(nèi)存單元main 函數(shù) EBP 值出棧程序跳轉(zhuǎn)到函數(shù)調(diào)用結(jié)束后需要繼續(xù)執(zhí)行的指令地址棧頂指針 ESP 向下移動(dòng)(跳過(guò) f 函數(shù)入棧參數(shù))f 函數(shù)參數(shù)出棧inline 函數(shù)目的:解決程序中
12、函數(shù)調(diào)用的效率問(wèn)題。使用:inline 函數(shù)適用于函數(shù)體代碼短,但是頻繁調(diào)用的函數(shù)。實(shí)現(xiàn):程序編譯時(shí),編譯器將程序中出現(xiàn)的內(nèi)聯(lián)函數(shù)的調(diào)用表達(dá)式用內(nèi)聯(lián)函數(shù)的函數(shù)體來(lái)進(jìn)行替換。缺點(diǎn):增加目標(biāo)程序代碼量,進(jìn)而增加空間開(kāi)銷,優(yōu)點(diǎn):減少因?yàn)楹瘮?shù)調(diào)用引起的開(kāi)銷,主要是參數(shù)壓棧、棧幀開(kāi)辟與回收,以及寄存器保存與恢復(fù)等。注意:在內(nèi)聯(lián)函數(shù)內(nèi)不允許用循環(huán)語(yǔ)句和開(kāi)關(guān)語(yǔ)句。所有對(duì)虛函數(shù)的調(diào)用都會(huì)使inlining 落空。編譯器通常不對(duì)通過(guò)指針而進(jìn)行的調(diào)用實(shí)施 inlining malloc 和 new1.211.22memmove、memcpy、memset、strcpy 和 mem1.23ymemcpy 和 mem
13、move 都是將源地址的若干個(gè)字符拷貝到目標(biāo)地址。如果源地址和目標(biāo)地址有,則 memcpy 不能保證拷貝正確,但 memmove 可以保證拷貝正確。void* memcpy( void *dest, const void *src, size_t count)char* pdest = sic_cast( dest );const char* psrc = sic_cast( src );assert(dest!=NULL & src!=NULL);assert(pdest = psrc+count | psrc = pdest+count); while(count-) 0)mallocne
14、w返回值返回 void*需要類型轉(zhuǎn)換返回指針帶有類型信息參數(shù)需要指定分配空間大小無(wú)需指定分配空間大小初始化不初始化調(diào)用構(gòu)造函數(shù)*pdest+ = *psrc;return dest;void* memmove( void *dest, const void *src, size_t count)if(count=0)return dst;char* pdest = sic_cast( dest );const char* psrc = sic_cast( src );if(dest=NULL & src=NULL) return dest;if(pdest = psrc+count | pde
15、st 0)*pdest+ = *psrc+;elsepdest += count; psrc += count;for(i=0;icount;i+)*(-pdest) = *(-psrc);return dest;void* memset( void *dest,val, size_t count)char* pdest = sic_cast( dest );assert(dest!=NULL); while(count-) 0)*pdest+ = (char)val;return dest;char* strcpy( char *dest, const char *src)i =0;asse
16、rt(dest!=NULL & src!=NULL); while( (*(dest+i)=*(src+i) != 0 )i+;return dest;C+隱式轉(zhuǎn)換C+隱式轉(zhuǎn)換發(fā)生條件:在混合類型表達(dá)式中,操作數(shù)被轉(zhuǎn)換成相同的類型用作 if 語(yǔ)句或循環(huán)語(yǔ)句的條件時(shí),被轉(zhuǎn)換為 bool 類型用于 switch 語(yǔ)句時(shí),轉(zhuǎn)為整數(shù)類型用來(lái)初始化某個(gè)變量(包括函數(shù)實(shí)參、return 語(yǔ)句),轉(zhuǎn)為變量的類型類隱式轉(zhuǎn)換:class Fruitstring name;/定義一個(gè) name 成員string colour;/定義一個(gè) colour 成員public:Fruit(const string &ns
17、t,const string &cst = green):name(nst),colour(cst)/構(gòu)造函數(shù) bool isSame(const Fruit &otherFruit)main()Fruit apple(apple);coutapple = /apple/ ?:apple.isSame(string(apple);可以用單個(gè)實(shí)參來(lái)調(diào)用的構(gòu)造函數(shù)定義了從形參類型到該類型的一個(gè)隱式轉(zhuǎn)換。 String(“apple”)隱式轉(zhuǎn)換為 Fruit。在構(gòu)造函數(shù)前面加 explicit 關(guān)鍵字,再隱式轉(zhuǎn)換就會(huì)導(dǎo)致編譯失敗。類隱式反向轉(zhuǎn)換:Class Fontpublic:1.24operat
18、or Fon private:ndle() const return f;/隱式轉(zhuǎn)換函數(shù)Fonndle f;void chageFontSize(Fonndle f,newSize)Font f;w;changeFontSize(f, w);/f 隱式從 Font 轉(zhuǎn)換為 FonndleC+強(qiáng)制類型轉(zhuǎn)換(盡量少做動(dòng)作)1.25C 風(fēng)格(C-style)強(qiáng)制語(yǔ)法:(T) exdivs/ cast exdivsto be of type T函數(shù)風(fēng)格(Function-style)強(qiáng)制語(yǔ)法:T(exdivs) / cast exdivsto be of type T。兩種形式之間沒(méi)有本質(zhì)上的不同,稱
19、為舊風(fēng)格(old-style)的強(qiáng)制(1) sic_cast ( expres)用來(lái)強(qiáng)迫隱式轉(zhuǎn)換,而且返回的是個(gè)副本!把 expres轉(zhuǎn)換為 type-id 類型,expres和 type-id 必須是指針、算術(shù)類型或枚舉類型。,但沒(méi)有運(yùn)行時(shí)類型檢查來(lái)保證轉(zhuǎn)換的安全性。sic_cast ( expres)用法:(1) 類層次結(jié)構(gòu)中基類類之間指針或的轉(zhuǎn)換。進(jìn)行上行轉(zhuǎn)換(把子類的指針或轉(zhuǎn)換成基類表示)是安全的;進(jìn)行下行轉(zhuǎn)換(把基類指針或轉(zhuǎn)換成子類表示)時(shí),由于沒(méi)有動(dòng)態(tài)類型檢查,所以是不安全的。double *d = sic_cast(&n) /無(wú)關(guān)類型指針轉(zhuǎn)換,編譯錯(cuò)誤(2) 基本數(shù)據(jù)類型之間的轉(zhuǎn)
20、換,如把轉(zhuǎn)換成 char,把轉(zhuǎn)換成 enum。n = 6; double d = sic_cast(n);把空指針轉(zhuǎn)換成目標(biāo)類型的空指針。把任何類型的表達(dá)式轉(zhuǎn)換成 void 類型。void *p = sic_cast(pn);(2)dynamic_cast ( expres)主要用來(lái)執(zhí)行“安全向下“。把 expres轉(zhuǎn)換成 type-id 類型的對(duì)象。type-id必須是類的指針、類的或者void *;如果 type-id 是類指針類型,那么 expres也必須是一個(gè)指針,如果 type-id 是一個(gè),那么 expres也必須是一個(gè)。dynamic_cast 主要用于類層次間的上行轉(zhuǎn)換和下行轉(zhuǎn)
21、換,還可以用于類之間的交叉轉(zhuǎn)換。如果 expres類型是 type-id 的基類,運(yùn)行時(shí)檢查是否expres實(shí)際是一個(gè)指向 type-id 類型的完整對(duì)象,如果是,結(jié)果返回指向 type-id 類型的完整對(duì)象,否則返回 NULL。BaseClass *pb = dynamic_cast(pd); /子類-父類,正確DerivedClass *pd2=dynamic_cast(pb2);/父類-子類,結(jié)果 NULL(3)const_cast (expres)用來(lái)修改類型的 const 或 volatile 屬性。除了 const 或volatile 修飾之外,type_id和 exdivs的類型
22、是一樣的。常量指針被轉(zhuǎn)化成非常量指針,并且仍然指向原來(lái)的對(duì)象;常量被轉(zhuǎn)換成非常量,并且仍然指向原來(lái)的對(duì)象;常量對(duì)象被轉(zhuǎn)換成非常量對(duì)象。const SA ra; /ra.i = 10; /直接修改 const 類型,編譯錯(cuò)誤SA &rb = const_cast(ra); rb.i = 10;比方說(shuō)有些函數(shù)對(duì)其參數(shù)只讀不寫,但卻只接受非 const 指針變量!reinpreter_cast(expres)(4)ret_cast 用于底層的強(qiáng)制,實(shí)際動(dòng)作可能取決于編譯器。例如,將一re個(gè)指針指針、 re為一個(gè)整數(shù),也可以把一個(gè)整數(shù)轉(zhuǎn)換成一個(gè)指針。type-id 必須是一個(gè)、算術(shù)類型、函數(shù)指針或者成
23、員指針。ret_cast 最普通的用途就是在函數(shù)指針類型之間進(jìn)行轉(zhuǎn)換。doSomething()return 0;typedef void(*FuncPtr)(); /FuncPtr 函數(shù)指針類型ret_cast(&doSomething); /函數(shù)指針類型轉(zhuǎn)換FuncPtr funcPtr= re注意:reinpreter_cast 僅僅重新解釋類型,但沒(méi)有進(jìn)行二進(jìn)制的轉(zhuǎn)換。ret_cast(n); 在進(jìn)行計(jì)算以后, d 包含無(wú)用值. 這n=9; double d=re是因?yàn)?re1.26 template 模板ret_cast 僅僅是n 的比特位到 d, 沒(méi)有進(jìn)行必要的分析。templat
24、e與 template意義完全相同。 typename 關(guān)鍵字:template class X private:typename T:id i;在模板中,類型 T 限定了類型 id。 也就是說(shuō) id 取決于 T。這種情況下,編譯器不知道 id 是類型T 中的靜態(tài)成員變量,還是 T 的嵌套類。通過(guò) typename 告訴編譯器將 T:id當(dāng)作類型,然后template 參數(shù):個(gè)變量 i,所以 typename 不可以出現(xiàn)在 T 的嵌套類前。template中的參數(shù)分為類型參數(shù)(T)和非類型參數(shù)(n)可以通過(guò)函數(shù)參數(shù)或者 class 的成員變量替換 template 非類型參數(shù)消除代碼膨脹tem
25、plate 隱式接口約束:template void doProsing(T &w)if (w.size() 10 & w != someNastyWidget) 對(duì)于 T(w 的類型)的隱式接口約束:(1) 它必須提供一個(gè)名為 size 的返回一個(gè)正數(shù)值的member function(成員函數(shù))。 operator!= 函數(shù)。(2) 它必須支持一個(gè)用于比較兩個(gè)類型template化:template化在編譯期執(zhí)行。如果又是 float,無(wú)法確定類型,報(bào)錯(cuò)。template 特化:template class Compare/ speT 的對(duì)象的化時(shí)無(wú)法確定參數(shù)類型會(huì)報(bào)錯(cuò),例如 5 既是li
26、ze for floattemplateclass Compare/ spelize for doubletemplate class MsgSender /不含 send()方法template class LoggingMsgSender: public MsgSenderpany 特化為 CompanyZ 時(shí),代碼不合法,特化的void sendClearMsg()send();MsgSender 不提供一般性的 template 接口令編譯器不會(huì)因?yàn)橛锌赡苓M(jìn)入特例化基類而使代碼失效的 3 個(gè)方法:(1) 使用 this-,this-send ();(2) 使用 using式,using
27、 MsgSender:send();(3) 明確被調(diào)用函數(shù)位于 base class 內(nèi),MsgSender:send()使用非類型參數(shù)在編譯期計(jì)算階乘:templatestruct Factorialenum value=n*Factorial:value; templatestruct Factorial enum value=1; coutFactorial:value派生類作用域-基類作用域-namespace 作用域-全局作用域內(nèi)層作用域中,如果內(nèi)層的作用域的函數(shù)或變量與外層作用域函數(shù)或變量同名,則會(huì)外層的函數(shù)或變量。例如派生類函數(shù)和基類函數(shù)同名會(huì)覆蓋基類函數(shù)(virtualfunc
28、tions 除外)。內(nèi)層作用域變量修改與外層作用域同名變量無(wú)關(guān)。main()i=0;1.30for (i=1; i= 5; +i)cout i;/輸出 1,2,3,4,5,覆蓋外層作用域的 icout i;/輸出 0,for 循環(huán)作用域中變量 i 的修改與 main 函數(shù)作用域中變量 i 無(wú)關(guān)typeid是個(gè)操作符,不是函數(shù)。typeid 操作符的返回結(jié)果是名為 type_info 的標(biāo)準(zhǔn)庫(kù)類型的對(duì)1.31象的。()返回類型的字符串,類型名字用系統(tǒng)相關(guān)的方法產(chǎn)生。cout typeid().name() endl;/輸出Derived d;Base &b2 =d;cout typeid(b2)
29、.name() endl/輸出 Base如果 Base 不包含虛函數(shù), typeid 的結(jié)果表達(dá)式的類型是 Base為 Base 加上一個(gè)虛函數(shù),couttypeid(b2).name()0 & y0)assert(xy);elseassert(ux);6.4 宏不是類型定義 #define T1 struct foo * typedef struct foo *T2;T1 a,b;/a 是 foo 型指針,b 是 foo 類型T2 a,b;/都是 foo 型指針大大1.511.52面1.531.54象(深入探索 C+對(duì)象模型)象 3 個(gè)特性:封裝性,繼承性,多態(tài)性面C 的結(jié)構(gòu)體變成 C+封裝
30、后的布局成本(主要的額外負(fù)擔(dān)由 virtual 引起):1、 virtual function 機(jī)制,用以支持一個(gè)有效率的“執(zhí)行期綁定”2、 virtual base class 用以實(shí)現(xiàn)“多次出現(xiàn)在繼承體系中的 base class,有一個(gè)單一而被共享的實(shí)體”C+對(duì)象模式C+有兩種 class data members:sic 和 nonsic三種 class member function:sic,nonsic 和 virtual簡(jiǎn)單對(duì)象模型:一個(gè) object 就是一系列的 slots,一個(gè) slot 指向一個(gè) member表格驅(qū)動(dòng)對(duì)象模型:一個(gè) object 含兩個(gè)指針,分別指向兩個(gè)表
31、:一個(gè)是 data member table,另一個(gè) member function table這個(gè)含有多個(gè) slot,每個(gè) slot 指向一個(gè)成員函數(shù)1.55C+對(duì)象模型:Nons之外,sic 和 nons個(gè)步驟支持之:ic data members 放在每個(gè) object 內(nèi),sic data members 在 object ic function members 也在 object 之外。Virtual functions 則以兩1、 每個(gè) class 生成一個(gè)存放虛函數(shù)指針的 virtual table(vtbl)2、 每個(gè) class object 被添加一個(gè)指針,指向相關(guān) vtb
32、l,這個(gè)指針被稱為 vptr。Vptr的第一個(gè) slot 通常是每個(gè)class 所關(guān)聯(lián)的 type_inof object。vptr 的設(shè)定和重置都有每個(gè) class 的構(gòu)造、析構(gòu)和拷貝構(gòu)造函數(shù)自動(dòng)完成優(yōu)點(diǎn): 空間和存取時(shí)間的效率缺點(diǎn):如果程序代碼未改變,但是 objects 的 nons ic data members 有所修改,就需要重新編譯。Class object 的內(nèi)存需求1、nonsic data members 的總和大小 2、任何猶豫 alignment 的需求而填補(bǔ)上去的空1.56間 3、為了支持 virtual 而由產(chǎn)生的任何額外負(fù)擔(dān)指針的類型:指針類型會(huì)教導(dǎo)編譯器如何解釋
33、某個(gè)特定地址中的內(nèi)存內(nèi)容及其大小。這也就解釋了一個(gè)指向地址 1000 的類型為 void*的指針,不能通過(guò)它進(jìn)行 object 操作 Class object 的內(nèi)存布局class ZooAnimal public: ZooAnimal();virtual ZooAnimal(); virtual void roe();protected:loc;/4 字節(jié)string name;/8 字節(jié);一個(gè) ZooAnimal 指針講橫跨地址空間 10001015(4+8+4)加上多態(tài)class Bear:public ZooAnimal public: Bear();Bear();void roe()
34、;virtual void dance(); protected:enum Dan;1.571.58Dandan_know;cell_block;Bear b(“Yogi”); Bear *pb = &b;Bear b; ZooAnimal *pz = &b; Bear *pb = &b;pz 和pb 都指向Bear object 的第一個(gè)byte。差別是pb 所涵蓋的地址包含整個(gè)Bear object。而 pz 所涵蓋的地址只包含 ZooAnimal 部分。除了 ZooAnimal subobject 中出現(xiàn)的 members,不能使用 pz 來(lái)直接處理 Bear 的任何members,vi
35、rtual 機(jī)制除外。剩下一部分:深度探索 C+對(duì)象模型 P30自動(dòng)默認(rèn)構(gòu)造函數(shù)1.59編譯器在需要的時(shí)候會(huì)為沒(méi)有任何構(gòu)造函數(shù)的類自動(dòng)一個(gè)默認(rèn)構(gòu)造函數(shù),但是需要注意的是,該的構(gòu)造函數(shù)只會(huì)執(zhí)行編譯器所需要的行動(dòng),其他變量參數(shù)它不會(huì)幫你進(jìn)行任何操作,比方說(shuō)成員不會(huì)幫你初始化為 0 的!編譯器會(huì)自動(dòng)默認(rèn)構(gòu)造函數(shù)的四種情況:1) A 自身沒(méi)有任何構(gòu)造函數(shù),但內(nèi)含一個(gè)有默認(rèn)構(gòu)造函數(shù)的 member object B的默認(rèn)構(gòu)造函數(shù)執(zhí)行的操作是調(diào)用 B 的 member object 的默認(rèn)構(gòu)造函數(shù)。 如果已經(jīng)有 A 的默認(rèn)構(gòu)造函數(shù),并初始化了 A 的某內(nèi)置類型對(duì)象。則編譯器會(huì)優(yōu)化 A 的默認(rèn)構(gòu)造函數(shù),調(diào)用
36、 B 的默認(rèn)構(gòu)造函數(shù)操作!如果有多個(gè) class member objects 都需要 A 的默認(rèn)構(gòu)造函數(shù)進(jìn)行初始化,則 C+會(huì)以這些對(duì)象在 class 中的次序來(lái)調(diào)用各類的默認(rèn)構(gòu)造函數(shù)2) A 自身沒(méi)有任何默認(rèn)構(gòu)造函數(shù)的類派生于一個(gè)帶有默認(rèn)構(gòu)造函數(shù)的基類它將調(diào)用上一層基類的默認(rèn)構(gòu)造函數(shù)。對(duì)一個(gè)后繼派生類來(lái)說(shuō),供的沒(méi)有區(qū)別。如果 A 沒(méi)有默認(rèn)構(gòu)造但有很多其他的構(gòu)造函數(shù),編譯器不會(huì)的和明確提新的默認(rèn)構(gòu)造函數(shù),而是直接擴(kuò)展已有的每一個(gè)構(gòu)造函數(shù),加入調(diào)用基類的默認(rèn)構(gòu)造函數(shù)3) 帶有一個(gè)虛函數(shù)的 classClass(或繼承)一個(gè) virtual functionClass 派生自一個(gè)繼承串鏈,其中有
37、一個(gè)或要有默認(rèn)構(gòu)造函數(shù)設(shè)置 vtbl 和 vptr4) 帶有一個(gè)虛基類的 class的 virtual base classes一種做法,派生類對(duì)象在每一個(gè)虛基類中安插一個(gè)指針,由指針指向虛基類。這個(gè)指針是在 class object 建構(gòu)期間被完成的Copy Constructor 的建構(gòu)操作(構(gòu)造函數(shù))1.60如果程序員沒(méi)有copy constructor,編譯器將自動(dòng)生成生成 default copy constructor,default copy constructor 使用 bitwise copy(按位拷貝會(huì)把 vptr 也一模一樣都拷貝過(guò)去,但是如果派生類用 bitwise c
38、opy 拷貝給基類的話,基類的 vptr 指向的就不是自己的虛函數(shù)表了,指向的是派生類的虛函數(shù)表,所以,這種情況下不能使用按位拷貝)編譯器不使用 bitwise copy 的 default copy constructor 四種情況:calss 內(nèi)含 member object,member object 有copy constructorclass 繼承自 base class,base class 有 copy constructor(3) classvirtual functions(4) class 繼承鏈中有 virtual base class前兩種情況中編譯器必須將 membe
39、r 或 base class 的構(gòu)造調(diào)用操作按吵到被的構(gòu)造函數(shù)中。第三點(diǎn)參看上面紅色話。第四點(diǎn)中,一個(gè) class object 如果以另一個(gè) object 作為初值,而后者有一個(gè)虛基類subobject,那么會(huì)使按位拷貝 sems 失效。P60bitwise copy,又名 shallow copy,是淺。memberwise copy,又名 deep copy,是深。注意:(1)A(A other)參拷貝到實(shí)參會(huì)調(diào)用構(gòu)造函數(shù)中傳入的參數(shù)是 A 的一個(gè)實(shí)例。由于是傳值,把形構(gòu)造函數(shù)。因此如果允許構(gòu)造函數(shù)傳值,那么會(huì)形成永無(wú)休止的遞歸并造成棧溢出。因此 C+的標(biāo)準(zhǔn)不允許構(gòu)造函數(shù)傳值參數(shù),而必須
40、是傳或者常量,例如 A(A &other)和 A(const A &other)。(2)函數(shù)中傳入的參數(shù)是 class 的實(shí)例時(shí),調(diào)用 copy constructor;函數(shù)中傳入的參數(shù)是class 的指針或者時(shí),不調(diào)用 copy constructor;函數(shù)的返回值為 class 的實(shí)例時(shí),編譯器會(huì)將 X fun()X result=; return result)轉(zhuǎn)化為 fun(X &result)result=; return;,避免返回值時(shí)調(diào)用 copy constructor,稱為 NRV(Named Return Value)優(yōu)化。= fun();/就是這個(gè)意思了!(3)派生類對(duì)象
41、時(shí),對(duì)于派生類繼承的基類成員變量也要。對(duì)于基類的 privatedata member,派生類可以通過(guò)調(diào)用基類的函數(shù)賦值函數(shù)防止自我賦值并且返回 reference to *thisWidget& Widget:operator=(const Widget &rhs)if(this=rhs)return *this;return *this;C+自動(dòng)生成的函數(shù)。1.611.62如果程序員沒(méi)有constructor, destructor, copy constructor, copy assignment operator,編譯器將自動(dòng)生成這些函數(shù)。如果要可以將函數(shù)C+自動(dòng)生成的函數(shù)(cons
42、tructor,copy constructor,copy assignment operator),為 private 而且故意不實(shí)現(xiàn)。構(gòu)造函數(shù)和析構(gòu)函數(shù)(1) 如果程序員沒(méi)有1.63任何 constructor,編譯器將自動(dòng)生成 default constructor,default constructor 沒(méi)有參數(shù),只執(zhí)行編譯器所需的行動(dòng),不會(huì)對(duì)成員變量進(jìn)行初始化(例如將整形變量初始化為 0)(2) polymorphic base class 應(yīng)該virtual destructor,避免部分 destructor。構(gòu)造函數(shù)的名字必須與類名相同,可以有任意類型的參數(shù),但不能具有返回類型
43、;析構(gòu)函數(shù)的名字必須與類名相同,但它前面必須加一個(gè)波浪號(hào),析構(gòu)函數(shù)沒(méi)有參數(shù),也沒(méi)有返回值,而且不能被重載。使用無(wú)參數(shù)構(gòu)造函數(shù)定義對(duì)象,不需要加括號(hào)。class Test Test() Test t();定義出錯(cuò),編譯正確,但不會(huì)調(diào)用構(gòu)造函數(shù)。Test t;定義正確,調(diào)用構(gòu)造函數(shù)。構(gòu)造函數(shù)調(diào)用順序:(1) virtual base class 調(diào)用構(gòu)造函數(shù)(virtual base class 的構(gòu)造函數(shù)由最底層 derived class 調(diào)用,其他 derived class 不再調(diào)用其構(gòu)造函數(shù),通過(guò) most_derived 標(biāo)識(shí)符確定是否調(diào)用 virtual base class 的構(gòu)造
44、函數(shù))(2) base class 按順序調(diào)用構(gòu)造函數(shù)(3) vptr 重置,指向當(dāng)前 class 的 virtual tablemember object 按調(diào)用自身構(gòu)造函數(shù)析構(gòu)函數(shù)調(diào)用順序:調(diào)用自身析構(gòu)函數(shù)member object 按順序調(diào)用構(gòu)造函數(shù)順序的相反順序調(diào)用析構(gòu)函數(shù)(3) vptr 重置,指向適當(dāng)?shù)?base class 的 virtual table(4) base class 按順序的相反順序調(diào)用析構(gòu)函數(shù)(5) virtual base class 按原構(gòu)造順序的相反順序調(diào)用析構(gòu)函數(shù)sic object 的構(gòu)造和析構(gòu)global sic object:_sti()函數(shù)進(jìn)靜態(tài)
45、初始化操作和_std()函數(shù)進(jìn)行靜態(tài)內(nèi)存 main()函數(shù)前調(diào)用,_std()函數(shù)在 main()結(jié)束前調(diào)用。操。local sic object:第一次進(jìn)入函數(shù),臨時(shí)對(duì)象為 false,constructor 被調(diào)用,然后臨時(shí)對(duì)象改為 true。destructor 在與”text program file”(例如 sic.c)有關(guān)的靜態(tài)內(nèi)存函數(shù)中被調(diào)用。為了 local sic objects 能夠按照構(gòu)造的相反順序調(diào)用 destructor,需要對(duì)產(chǎn)生出來(lái)的 local sic objects 保持一個(gè)執(zhí)行期鏈表。 array object: 使用 vec_new()的函數(shù),生成 cla
46、ss object 數(shù)組。 vec_new(void *array,/*數(shù)組起始地址*/size_em_size,/*每個(gè) class object 大小*/ elem_count,/*數(shù)組元素?cái)?shù)目*/void (*constructor)(void*),/*constructor 函數(shù)指針*/ void(*destructor)(void*)/*destructor 是函數(shù)指針*/對(duì)于明顯獲得初值的元素,vec_new 不再有必要。p10=Po(),Po(1,1,5),Po(),明確初始化前 3 個(gè)元素,vec_new 只初始化后Po7 個(gè)元素。初始化C+中類的成員不會(huì)默認(rèn)初始化(整形初始化
47、為 0)1.64C+使用初始化列表 Po:Po(初始化的順序取決于變量的x,y):x(x),y(y)進(jìn)行初始化次序,與初始化列表的次序無(wú)關(guān)C+規(guī)定對(duì)象變量的初始化動(dòng)作發(fā)生在進(jìn)入構(gòu)造函數(shù)體之前決不再構(gòu)造和析構(gòu)過(guò)程中調(diào)用 virtual 函數(shù)盡量不要在初始化時(shí)使用virtual function,因?yàn)関ptr 的設(shè)置和初始化的順序并不確定,可能無(wú)法調(diào)用正確的 virtual function。如果需要調(diào)用 virtual function,可以在構(gòu)造函數(shù)體內(nèi)調(diào)用。Po :Po ( x, y)this-x=x;this-y=y;是賦值,不是初始化函數(shù)內(nèi)的s ic object 稱為local s i
48、c object,其他s ic object 稱為non-local satic object C+對(duì)定義于不同編譯單元的 non-local s ic object 的初始化次序無(wú)明確定義。如果某編譯單元的 non-local s ic ojbect 的初始化動(dòng)作使用了另一個(gè)編譯單元的 non-local s ic object,所用的 oject 可能尚未初始化。解決方法是將 non-s ic local s ic object移動(dòng)到自己專屬的函數(shù)內(nèi)。這些函數(shù)返回一個(gè) reference 指向它所含對(duì)象,然后用戶調(diào)用這些函數(shù),而不直接涉及這些對(duì)象。EffectiveC+條款 04字節(jié)對(duì)齊1
49、.65計(jì)算機(jī)系統(tǒng)中以 byte 為數(shù)據(jù),不同數(shù)據(jù)類型所占的空間不同,如:占 4 個(gè)字節(jié),char 占一個(gè)字節(jié),short 占兩個(gè)字節(jié)計(jì)算機(jī)為了快速的讀寫數(shù)據(jù),默認(rèn)情況下將數(shù)據(jù)存放在某個(gè)地址的起始位置,如:類型默認(rèn)在地址能被 4整除的起始位置,char 可以存放在任何地址位置(被 1 整除),short 類型能被 2 整除的其實(shí)位置。這是默認(rèn)字節(jié)對(duì)齊。在地址#pragma pack(n)來(lái)設(shè)定變量以 n 字節(jié)對(duì)齊方式。n 字節(jié)對(duì)齊就是說(shuō)變量存放的起始地址的偏移量有兩種情況:第一、如果 n 大于等于該變量所占用的字節(jié)數(shù),那么偏移量必須滿足默認(rèn)的對(duì)齊方式,第二、如果 n 小于該變量的類型所占用的字節(jié)
50、數(shù),那么偏移量為 n 的倍數(shù),不用滿足默認(rèn)的對(duì)齊方式。類的大小1.66空類的大小為 1 字節(jié),會(huì)入一個(gè) char 以確保空類實(shí)例化有獨(dú)一無(wú)二的地址。一個(gè)空基類 X,兩個(gè)派生類 Y,Z承自 X,派生類 A 繼承自Y 和 Z類大小主要受三點(diǎn)影響:1、語(yǔ)言本身造成的負(fù)擔(dān) 2、編譯器的特別處理 3、對(duì)齊限制則在未特別處理empty virtual base class 的編譯器情況下,X 的 sizeof 大小是 1 個(gè)字節(jié), Y 和 Z 是 8,A 的大小是 12有特別處理的編譯器中,X 為 1,Y 和 Z 是 4,A 是 8 個(gè)字節(jié)大小class A;/sizeof 大小為 1class B:vi
51、rtual public A;class C:virtual public A;/sizeof 大小為 4 class D:public B,public C;/sizeof 大小為 8class E:public B; class F:public C;/sizeof 大小為 4 class G:public E, public F;/sizeof 大小為 8class H:virtual public B;class I:virtual public C;/sizeof 大小為 8 class J:public H, public I;/sizeof 大小為 16成員函數(shù),靜態(tài)成員變量與類
52、的大小無(wú)關(guān)的。虛函數(shù)需要指針指向虛函數(shù)表,虛基類需要指針指向虛基類,每個(gè)指針大小占4 字節(jié)。類的大小遵守字節(jié)對(duì)齊,調(diào)整規(guī)則。成員變量成員變量布局:1.67同一 acs section 中 data member 不一定是連續(xù)的,只要符合后在高地址即可(邊界調(diào)整就需要填補(bǔ)一些 bytes),多個(gè) acs section 中的 data member排列。凡處于同一 acs sections 中的數(shù)據(jù),排列必定保證以其次序出現(xiàn)在內(nèi)存布局當(dāng)中。vptr 放在 class object 最前端或者最后,取決于編譯器(或者任何哪里)。C+標(biāo)準(zhǔn)允許編譯器將多個(gè) acs sections 的 data me
53、mbers排列,但是現(xiàn)在一般都是各 sections 連鎖在一起,依照的次序,成為一塊連續(xù)區(qū)塊base class data member 先出現(xiàn),virtual base class data member 在最后。成員變量存?。簊ic data member 存取:sic data member 只有一個(gè)實(shí)體,存放在數(shù)據(jù)段中,每次訪問(wèn)內(nèi)化為對(duì)唯一實(shí)體的直接origin.sum 內(nèi)化為 Po:sum。sic member 的地址是指向 sic member 數(shù)據(jù)類型的指針,&Po:sum 的類型是*。如果兩個(gè) class 的sic member 同名(它們都被放在程序的 data segme
54、nt 里),編譯器會(huì)對(duì) sic member編碼,稱為 name-mangling。non-sic data member 存?。簄on-sic member 存放在每個(gè) class object 中。Po3d *pt3d; pt3d-x = 0.0; 其執(zhí)行效率在x 是一個(gè)struct member、一個(gè) class member、單一繼承、多重繼承的情況下都完全相同。但 x 是一個(gè) virtual base class 的 member,存取速度會(huì)比較慢一點(diǎn)。即對(duì)于多態(tài),data member 的 offset 必須到執(zhí)行期的時(shí)候才能確定.問(wèn)題:Po3d origin, *pt=&orig
55、in;origin.x=0.0; pt-x=0.0;通過(guò) origin 和 pt 存取大差異嗎?(p99)重單一繼承中,data member 是直接存放在 class object 中,引入繼承不影響存取效率。具體繼承(相對(duì)于虛擬繼承)并不會(huì)增加空間活存取時(shí)間上的額外負(fù)擔(dān)成員函數(shù)三種類型的成員函數(shù):1.68(1)sic member functions只能存取sic data member,不能存取 non-sic data membe。不能為const,volatile 或 virtual。(連 this 指針都沒(méi)有,當(dāng)然不能non-sic member functions為 const
56、了)(2)non-s ic member functions 會(huì)內(nèi)化為 non-member 的形式,p-Po :fun()內(nèi)化為 Po :fun(p),其中 p 就是 this 指針,即使 p 是空指針仍然可以調(diào)用。如果 member functions 存取 non-s ic data member,空指針調(diào)用 member function 出錯(cuò)。virtual functionsclass object 內(nèi)含 N 個(gè) vptr 指向 virtual table(N 為 base class 數(shù)目)。virtual function調(diào)用會(huì)內(nèi)化為(*p-vptri)(p),其中 vptri
57、為指向 virtual function 的函數(shù)指針智能指針(同名 virtual function 在virtual table 中的索引值是相同的)。(3)多繼承單繼承中,base class 的指針和 derived class 指針都指向相同的起始地址,不需要修改地址;多繼承中,第二個(gè)或后繼的 base class 指針的地址需要修改地址。例如,Vertex3d 繼承自 Po3d 和 Vertex,Po3d 繼承自 Po2d。 Po2d *p2d; Po3d *p3d; Vertex *pv; Vertex3d v3d;p2d=&v3d 和 p3d=&v3d 不需要修改地址;pv=&v
58、3d 需要修改地址。多重繼承中,為解決歧義,必須明確指明調(diào)用哪個(gè) base class 內(nèi)的變量或函數(shù)。用 C+設(shè)計(jì)一個(gè)不能被繼承的類。(劍指 offer 面試題 48)template class MakeFinalfriend T; private:MakeFinal() MakeFinal() ;class FinalClass : virtual public MakeFinalpublic: FinalClass() FinalClass() ;FinalClass 使用與一般類沒(méi)有區(qū)別,盡管類 MakeFinal 的構(gòu)1.691.70造函數(shù)和析構(gòu)函數(shù)都是私有的,但由于類 Final
59、Class 是它的函數(shù),因此在FinalClass 中調(diào)用 MakeFinal 的構(gòu)造函數(shù)和析構(gòu)函數(shù)都不會(huì)造成編譯錯(cuò)誤。但從 FinalClass 繼承一個(gè)類并創(chuàng)建它的實(shí)例時(shí),卻不能通過(guò)編譯,例如 class Try : public FinalClass,由于類 FinalClass 是從類 MakeFinal 承過(guò)來(lái)的,在調(diào)用 Try 的構(gòu)造函數(shù)的時(shí)候,會(huì)直接跳過(guò)FinalClass 而直接調(diào)用MakeFinal 的構(gòu)造函數(shù)。Try 不是 MakeFinal 的能調(diào)用其私有的構(gòu)造函數(shù)。承,因此不1.71虛擬繼承中,virtual base class 只有一個(gè)實(shí)體。每個(gè)有 virtual
60、base class 的 class 必須有一個(gè)指針 vbptr 指向每個(gè) virtual base class。A 虛擬繼承自 B,B 虛擬繼承自 C,則 A 有兩個(gè)指針指向兩個(gè) virtual base class虛函數(shù)(1) virtual 函數(shù)表現(xiàn)在運(yùn)行期,是運(yùn)行期多態(tài)(動(dòng)態(tài)多態(tài)),函數(shù)重載和 template 參數(shù)具現(xiàn)化表現(xiàn)在編譯期,是編譯期多態(tài)(靜態(tài)多態(tài))。1.72(2) 類的實(shí)例不支持 virtual 函數(shù)多態(tài),類的指針和例如 Bear 繼承自 ZooAnimal,roe 是 virtual 函數(shù)支持 virtual 函數(shù)多態(tài)。zr.roe()/ 調(diào)用 Bear b; ZooAn
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年柴油發(fā)電組項(xiàng)目可行性研究報(bào)告
- 2025年旋軸項(xiàng)目可行性研究報(bào)告
- 2025年干衣機(jī)電動(dòng)機(jī)項(xiàng)目可行性研究報(bào)告
- 2025年四通遙控車項(xiàng)目可行性研究報(bào)告
- 2025至2031年中國(guó)交換機(jī)行業(yè)投資前景及策略咨詢研究報(bào)告
- 廣州廣東廣州市黃埔區(qū)衛(wèi)生健康局所屬事業(yè)單位廣州開(kāi)發(fā)區(qū)醫(yī)院招聘73人筆試歷年參考題庫(kù)附帶答案詳解
- 2025至2030年自動(dòng)裝配機(jī)械配件項(xiàng)目投資價(jià)值分析報(bào)告
- 2025至2030年中國(guó)自動(dòng)化螺釘緊固系統(tǒng)數(shù)據(jù)監(jiān)測(cè)研究報(bào)告
- 2025至2030年中國(guó)穿心電容數(shù)據(jù)監(jiān)測(cè)研究報(bào)告
- 2025至2030年平紋雙彈布項(xiàng)目投資價(jià)值分析報(bào)告
- 第八節(jié) 元代散曲
- 質(zhì)量體系工程師崗位說(shuō)明書
- 三年級(jí)上語(yǔ)文開(kāi)學(xué)第一課
- 烹飪刀工與原料成型技術(shù)課件
- 消防設(shè)施維護(hù)與日常檢查培訓(xùn)講義
- 最新安全生產(chǎn)管理教材電子版
- 良性陣發(fā)性位置性眩暈完整版本課件
- 典當(dāng)業(yè)務(wù)計(jì)劃方案
- 老化箱點(diǎn)檢表A4版本
- 音標(biāo)教學(xué)課件(共73張PPT)
- 2012數(shù)據(jù)結(jié)構(gòu)英文試卷A及答案
評(píng)論
0/150
提交評(píng)論