首頁 考試吧論壇 Exam8視線 考試商城 網絡課程 模擬考試 考友錄 實用文檔 求職招聘 論文下載 | ||
![]() |
2011中考 | 2011高考 | 2012考研 | 考研培訓 | 在職研 | 自學考試 | 成人高考 | 法律碩士 | MBA考試 MPA考試 | 中科院 |
|
![]() |
四六級 | 職稱英語 | 商務英語 | 公共英語 | 托福 | 雅思 | 專四專八 | 口譯筆譯 | 博思 | GRE GMAT 新概念英語 | 成人英語三級 | 申碩英語 | 攻碩英語 | 職稱日語 | 日語學習 | 法語 | 德語 | 韓語 |
|
![]() |
計算機等級考試 | 軟件水平考試 | 職稱計算機 | 微軟認證 | 思科認證 | Oracle認證 | Linux認證 華為認證 | Java認證 |
|
![]() |
公務員 | 報關員 | 銀行從業資格 | 證券從業資格 | 期貨從業資格 | 司法考試 | 法律顧問 | 導游資格 報檢員 | 教師資格 | 社會工作者 | 外銷員 | 國際商務師 | 跟單員 | 單證員 | 物流師 | 價格鑒證師 人力資源 | 管理咨詢師考試 | 秘書資格 | 心理咨詢師考試 | 出版專業資格 | 廣告師職業水平 駕駛員 | 網絡編輯 |
|
![]() |
衛生資格 | 執業醫師 | 執業藥師 | 執業護士 | |
![]() |
會計從業資格考試(會計證) | 經濟師 | 會計職稱 | 注冊會計師 | 審計師 | 注冊稅務師 注冊資產評估師 | 高級會計師 | ACCA | 統計師 | 精算師 | 理財規劃師 | 國際內審師 |
|
![]() |
一級建造師 | 二級建造師 | 造價工程師 | 造價員 | 咨詢工程師 | 監理工程師 | 安全工程師 質量工程師 | 物業管理師 | 招標師 | 結構工程師 | 建筑師 | 房地產估價師 | 土地估價師 | 巖土師 設備監理師 | 房地產經紀人 | 投資項目管理師 | 土地登記代理人 | 環境影響評價師 | 環保工程師 城市規劃師 | 公路監理師 | 公路造價師 | 安全評價師 | 電氣工程師 | 注冊測繪師 | 注冊計量師 |
|
![]() |
繽紛校園 | 實用文檔 | 英語學習 | 作文大全 | 求職招聘 | 論文下載 | 訪談 | 游戲 |
關于多態,關于 C多態 (polymorphism) 一詞最初來源于希臘語 polumorphos,含義是具有多種形式或形態的情形。在程序設計領域,一個廣泛認可的定義是“一種將不同的特殊行為和單個泛化記號相關聯的能力”。然而在人們的直觀感覺中,多態的含義大約等同于“同一個方法對于不同類型的輸入參數均能做出正確的處理過程,并給出人們所期望獲得的結果”,也許這正體現了人們對于多態性所能達到的效果所寄予的期望:使程序能夠做到越來越智能化,越來越易于使用,越來越能夠使設計者透過形形色色的表象看到代碼所要觸及到的問題本質。
在本文中我們使用一個簡單的單鏈表作為例子,展示 C 語言是如何體現多態性的。
結構體:不得不說的故事
許多從寫 C 代碼開始,逐漸走向 C++ 的程序員都知道,其實 C++ 里面的 class,其前身正是 C 語言中的 structure。很多基于 C 語言背景介紹 C++ 的書籍,在介紹到 class 這一章的時候都會向讀者清晰地展示,一個 C 語言里的 structure 是怎樣逐漸變成一個典型的 C++ class 的,甚至最后得出結論:“structure 就是一個所有成員都公有的類”,當然了,class 還是 class,不能簡單的把它看做一個復雜化了的 structure 而已。
下面我們來看看在 C 語言中定義一個簡單的存儲整型數據的單鏈表節點是怎么做的,當然是用結構體。大部分人會像我一樣,在 linkList.h 文件里定義:
typedef struct Node* linkList;
struct Node // 鏈表節點
{
int data; // 存儲的整型數據
linkList next; // 指向下一個鏈表節點
};
鏈表有了,下面就是你想要實現的一些鏈表的功能,當然是定義成函數。我們只舉幾個常用功能:
linkList initialLinklist(); // 初始化鏈表
link newLinkList (int data); // 建立新節點
void insertFirst(linkList h,int data); // 在已有鏈表的表頭進行插入節點操作
void linkListOutput(linkList h); // 輸出鏈表中數據到控制臺
這些都是再自然不過的 C 語言的編程過程,然后我們就可以在 linkList.c 文件中實現上述兩個函數,繼而在 main.c 中調用它們了。
然而上面我們定義的鏈表還只能對整型數據進行操作。如果下次你要用到一個存儲字符串類型的鏈表,就只好把上面的過程重新來過。也許你覺得這個在原有代碼基礎上做略微修改的過程并不復雜,可是也許我們會不斷的增加對于鏈表這個數據結構的操作,而需要用鏈表來存儲的數據類型也越來越多,這些都意味著海量的代碼和繁瑣的后期維護工作。當你有了上百個存儲不同數據類型的鏈表結構,每當你要增加一個操作,或者修改某個操作的傳入參數,工作量會變大到像一場災難。
但是我們可以改造上述代碼,讓它能夠處理你所想要讓它處理的任何數據類型:實行,字符型,乃至任何你自己定義的 structure 類型。
Void*:萬能的指針“掛鉤”
幾乎所有講授 C 語言課程的老師都會告訴你:“指針是整個 C 語言的精髓所在。”而你也一直敬畏著指針,又愛又恨地使用著它。許多教材都告訴你,int * 叫做指向整型的指針,而 char * 是指向字符型的指針,等等不一而足。然而這里有一個另類的指針家族成員—— void *。不要按照通常的命名方式叫它做指向 void 類型的指針,它的正式的名字叫做:可以指向任意類型的指針。你一定注意到了“任意類型”這四個字,沒錯,實現多態,我們靠的就是它。
下面來改造我們的鏈表代碼,在 linkList.h 里,如下:
typedef struct Node* linkList;
struct Node // 鏈表節點
{
void *data; // 存儲的數據指針
linkList next; // 指向下一個鏈表節點
};
linkList initialLinklist(); // 初始化鏈表
link newLinkList (void *data); // 建立新節點
void insertFirst(linkList h, void *data); // 在已有鏈表的表頭進行插入節點操作
void linkListOutput(linkList h); // 輸出鏈表中數據到控制臺
我們來看看現在這個鏈表和剛才那個只能存儲整型數據的鏈表的區別。
當你把 Node 結構體里面的成員定義為一個整型數據,就好像把這個鏈表節點打造成了一個大小形狀固定的盒子,你定義一個鏈表節點,程序進行編譯的時候編譯器就為你打造一個這樣的盒子:裝一個 int 類型的數據,然后裝一個 linkList 類型的指針。如果你想強行在這個盒子里裝別的東西,編譯器會告訴你,對不起,盒子的大小形狀并不合適。所以你必須為了裝各種各樣類型的數據打造出不同的生產盒子的流水線,想要裝哪種類型數據的盒子,就開啟對應的流水線來生產。
但是當你把結構體成員定義為 void *,一切都變得不同了。這時的鏈表節點不再像個大小形狀固定的盒子,而更像一個掛鉤,它可以掛上一個任意類型的數據。不管你需要存儲什么類型的數據,你只要傳遞一個指針,把它存儲到 Node 節點中去,就相當于把這個數據“掛”了上去,無論何時你都可以根據指針找到它。這時的鏈表仿佛變成了一排粘貼在墻上的衣帽鉤,你可以掛一排大衣,可以掛一排帽子,可以掛一排圍巾,甚至,你可以并排掛一件大衣一頂帽子一條圍巾在墻上。void * 初露猙獰,多態離 C 語言并不遙遠。
北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內蒙古 |