
方法有兩種:
第一種是將C++中的面向物件特征去掉,先全部理解源代碼的邏輯,然后改寫;第二種是在C中保留面向物件的部分特征,用結構體實作類的功能, 第一種方法,對于類的數目很少的情況還可以,
如果類的數目比較多,全部理解源代碼,然后重寫就很耗時間,而且很容易出錯,更甚者,如果遇到大的專案想全部理解源代碼幾乎是不可能的, hpijs程式中類有140多個,這個時候就需要采用第二個方法了,
你可以一個類一個類的改沒有什么太高的難度,如果不是筆誤的話,幾乎不會出錯,而且根本不需要理解程式邏輯,
也許改完后你對程式所要實作的功能還一無所知,倒不是說一無所知對大家有好處,只是想說這種方法的與程式邏輯本身的無關性,
下面對C++的一些特性,以及如何在c里實作或者替代,作一些初步的探討:
說明:
· 函式Ixx為類xx的建構式的實作,
· 原類的成員函式改為前綴為結構體名+‘_’的函式,
· 函式指標U為原類的解構式的宣告;
· U+結構體名稱為原類的解構式的實作;
· Fun-_+結構體名為對該結構體成員函式指標進行指向;
· 以后遇到上述情況將不再說明,
一.類的成員函式和資料成員 由于struct沒有對成員的訪問權限進行控制,必須加入額外的機制進行訪問控制,這樣一來就使得程式復雜化了,所以只能放棄訪問權限的控制,
1)對于類的資料成員可以直接轉為C中結構體的資料成員,
2)函式則需轉化為對應的函式指標,因為struct里不允許出現函式的宣告和定義,而函式前如果有virture,inline等修飾符也要去掉,如函式void funca(int a);改為void (*funca)(struct B *p,int a);
大家可以看到函式指標的原型里加了一個指標struct B的指標,這是因為要在函式內部對類的成員進行操作,要靠該指標指定結構體的成員,在類的成員函式里,實際上在引數列里也隱含有一個指向自身的this指標,
3)對于靜態成員則要定義成全域變數或全域函式,因為結構體中不能有靜態成員,
二.類的建構式 類在實體化的時候會呼叫類的預設建構式,在struct里,要定義一個同名函式指標指向一個具有建構式功能的初始化函式,與建構式不同的是,要在初始化函式里加入進行函式指標初始化的陳述句.使用的時候在創建結構體變數的時候要用malloc而不是new,并且這個時候要手工呼叫初始化函式,
如下例所示:
class A{public: A(); ~A(); void func(int a);private: int b;};A::A(){ b=0;}
void A::func(int a){ b=a;}
typedef struct classA A;struct classA{ void (*A)(struct classA *p);//建構式指標 void (*U)(struct classA *p);//解構式指標 void (*func)(struct classA *p,int a); int b;};
void fun_A(A *p){ p->func=classA_func; //將函式指標初始化}
void IA(A *p) //建構式,命名規則在類名前加I{ fun_A(p); p->b=0; //原建構式所作部分}
void classA_func(A *p,int a){ p->b=a;}
在使用的地方采用如下方式:· · · A *s=(A*)malloc(sizeof(A)); s->A=IA; s->A(s);
三.類的解構式
類的解構式所作的作業是釋放所占的資源,
在C中,無論是哪個struct都用函式指標U替代解構式,之所以所有的struct都用指標U是基于如下情況:
如果將子類指標賦給基類指標,基類指標在釋放的時候不必考慮呼叫哪個函式名的解構式,只需呼叫成員函式U即可,成員函式U需要像一般成員函式一樣在fun_類名()函式中指定,
類的解構式是由系統呼叫的,在C中則要顯式呼叫,至于何時呼叫,要準確判斷,四.類的拷貝建構式
類的拷貝建構式主要用途是加快以下情況下類的構建速度:
1. 作為引數傳給函式,(additem(Itema))
2. 作為函式回傳值,
3. 實體化類時作引數,
這三種情況下都是由系統直接呼叫類的拷貝建構式而不是建構式,
注意:C=D;不會呼叫拷貝建構式,這種情況下使用的是多載‘=’運算子的方法,(詳見運算子多載);
由于C中定義struct變數的時候,使用的全部是指標,不會用到拷貝建構式,所以暫不考慮,對于原來函式引數或者回傳值需要類變數的,要全部轉化為類指標的方式,實體化類時作引數的情況,可以通過另外定義一個帶引數的建構式來解決,
五.類的行內函式和虛函式
行內函式和虛函式的修飾符inline 、virture 要全部去掉,行內函式體則要去掉,將行內函式在外面定義成一個函式,如:
file:///C:\Users\Administrator.WIN-STED6B9V5UI\AppData\Local\Temp\ksohtml3684\wps5.jpg
class B{ … virture void funb(); inline int add()const {return a+b;};private: int a; int b; …}
改為:
file:///C:\Users\Administrator.WIN-STED6B9V5UI\AppData\Local\Temp\ksohtml3684\wps6.jpg
typedef classB B;struct classB{ … void (*funb)(struct classB *p); int (*add)(struct classB *p); int a; int b;}
void classB_funb(B *p){ …}
int classB_add(B *p){ return p->a+p->b;}
void fun_classB(B *p){ … p->funb=classB_funb; p->add= classB_add;}
六.多載
類中多載有函式多載和運算子多載兩種:
1)函式的多載
函式多載滿足的條件是:函式名相同,引數個數或者引數型別不同,
這樣在呼叫的時候,會根據你輸入的引數不同,呼叫不同的函式,
在C中只好分別起不同的名字,沒有別的解決辦法,
2)運算子多載
運算子多載只是為了滿足一般的運算子使用的習慣而又不會出現錯誤,
C中不支持運算子多載,可以定義一個函式實作該功能,
這是一般類的修改,
七.類的繼承
1)單繼承
如果類之間有繼承關系,先將基類按照一般類的改法,修改好,然后將基類的定義部分全部拷到子類的前頭,除了將基類的建構式名改為子類建構式名外,不可以將基類定義的部分作其他改動,
并在建構式里呼叫基類的建構式,然后如果子類覆寫了基類的函式,則要把該函式指標重定向到子類函式,這是為了保持類的繼承帶來的動態聯編的特性,
類之間的繼承關系是復雜且多變的,為了保證基類在所有子類中的唯一而且方便修改,最好的方法就是把基類的結構體部分做成宏,在子類中直接使用即可,
2)多繼承
我個人認為多繼承是最好不要用,他會帶來一些問題,會出現多個繼承路徑的問題,除非是為了方便編程而使用的,如繼承介面等等,
多繼承也是可以改的,將多個基類的成員全部拷到子類里,遇到重復的成員名,則在前面加上前綴來區別,當然這個指的是基類之間有相同的,如果是派生類和基類之間有重名的,則會覆寫基類,
八.其他
其他的還有一些比如模板的使用等等,這些都是為了方便編程,復用代碼,C中沒有,只好自己寫多個函式來分別實作,另外還有引數串列里的&符號要用指標替代,預設值也要去掉,而在呼叫的時候要注意將預設值寫上,
˙·………………………·˙`˙·…………………………·
另外如果你想更好的提升你的編程能力,學好C語言C++編程!彎道超車,快人一步!筆者這里或許可以幫到你~
分享(原始碼、專案實戰視頻、專案筆記,基礎入門教程)
歡迎轉行和學習編程的伙伴,利用更多的資料學習成長比自己琢磨更快哦!
免費學習書籍:

免費學習資料:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/263175.html
標籤:C++
上一篇:C++指標的算術運算 、關系運算
