日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言实现封装、继承、多态

發(fā)布時間:2024/4/11 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言实现封装、继承、多态 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

C語言實現(xiàn)封裝、繼承、多態(tài)

文章目錄

  • C語言實現(xiàn)封裝、繼承、多態(tài)
    • 一. 封裝
    • 二.繼承
    • 三. 多態(tài)

一. 封裝

C語言中雖然沒有類,但有struct和指針。我們可以在一個struct中存入數(shù)據(jù)和函數(shù)指針,以此來模擬類行為。

typedef struct _Parent {int a;int b;void (*print)(struct _Parent *This);}Parent;
  • 封裝性的意義在于,函數(shù)和數(shù)據(jù)是綁在一起的,數(shù)據(jù)和數(shù)據(jù)是綁在一起的。這樣,我們就可以通過簡單的一個結(jié)構(gòu)指針訪問到所有的數(shù)據(jù),遍歷所有的函數(shù)。封裝性,這是類擁有的屬性,當(dāng)然也是數(shù)據(jù)結(jié)構(gòu)體擁有的屬性。

二.繼承

  • 如果要完全地用C語言實現(xiàn)繼承,可能有點難度。但如果只是簡單的做一下,保證子類中含有父類中的所有成員。這還是不難的。
typedef struct _Child { Parent parent; int c; }Child;
  • 在設(shè)計C語言繼承性的時候,我們需要做的就是把基礎(chǔ)數(shù)據(jù)放在繼承的結(jié)構(gòu)的首位置即可。這樣,不管是數(shù)據(jù)的訪問、數(shù)據(jù)的強轉(zhuǎn)、數(shù)據(jù)的訪問都不會有什么問題。

三. 多態(tài)

  • 這個特性恐怕是面向?qū)ο笏枷肜锩孀钣杏玫牧恕?/li>
  • 要用C語言實現(xiàn)這個特性需要一點點技巧,但也不是不可能的。
#include <stdio.h> #include <stdlib.h>//模擬一個類A typedef struct A {void *vptr;//虛函數(shù)指針//下面內(nèi)容可以刪掉,寫上的目的:看著像一個類//成員變量int a;int b;void initA(A *p, int a, int b);//虛函數(shù)void dong1();void dong2(); }A;//實現(xiàn)虛函數(shù) void dong1() {printf("基類 dong1\n"); } void dong2() {printf("基類 dong2\n"); }//模擬虛表結(jié)構(gòu) typedef struct {void(*v1)();void(*v2)(); }Vtable;//模擬一個類中的虛表 Vtable A_Vtable = { &dong1, &dong2 };//精華在這:★a類可以調(diào)用dong1 dong2 這兩個函數(shù)★//模擬A類的構(gòu)造函數(shù) void initA(A *p, int a, int b)//第一個是this指針,在c++中也會默認(rèn)傳一個this指針 {p->vptr = &A_Vtable;p->a = a;p->b = b; }/////模擬派生類 B typedef struct B {A a;//父類的內(nèi)容//下面內(nèi)容可以刪掉,寫上的目的:看著像一個類int b;void dong11();void dong66();void initB(B* p, int a, int b); }B; //模擬派生類的虛函數(shù) void dong11()//模擬覆蓋dong1這個函數(shù) {printf("派生類 dong11\n"); } void dong66() {printf("派生類 dong66\n"); } //模擬子類虛表,增加了一個函數(shù)dong66 typedef struct {Vtable vtable;void(*p)(); }Vtable2;//子類的虛表 //注意這里大括號一個不能少 //★b類可以調(diào)用dong11、dong2、dong66 這三個函數(shù)★ Vtable2 B_vtable = { { &dong11, &dong2 }, &dong66 };//B類構(gòu)造函數(shù) //為什么要a參數(shù)呢?初始化基類 void initB(B* p,int a, int b) {//************重點**************//創(chuàng)建B類,但是需要初始化A類。繼承A類中的虛表指針//initA((A*)p, a, b); //我們這里用B類自己的虛表,一個類一個虛表p->a.vptr = &B_vtable; p->b = b; }/// //以下內(nèi)容全是模擬//測試一下A類 void test1() {A aa;initA(&aa, 10, 20);((Vtable*)aa.vptr)->v1();((Vtable*)aa.vptr)->v2(); }//測試一下B類 void test2() {//創(chuàng)建B類B *b = (B*)malloc(sizeof(B));initB(b, 10, 20);//轉(zhuǎn)成A類A *a = (A*)b;//現(xiàn)在表面上是父類,而我們可以調(diào)用父類沒有而子類有的方法((Vtable2*)(a->vptr))->p();printf("\n------見證奇跡的時候到了,實現(xiàn)多態(tài)------\n\n");((Vtable*)(a->vptr))->v1();//子類覆蓋了父類對象,調(diào)用的就是子類對象((Vtable*)(a->vptr))->v2();//子類沒有覆蓋父類對象,調(diào)用的就是父類對象 }//test3用來解惑的。其實我們b類不靠A就能調(diào)用父類,子類方法,test2實現(xiàn)的多態(tài)就是為了模擬C++ void test3() {B *b = (B*)malloc(sizeof(B));initB(b, 10, 20);//下面兩個地址是一樣的,這里得仔細(xì)考慮。我也是調(diào)試了好久才發(fā)現(xiàn)其中的奧秘printf("%d\n", b->a.vptr);printf("%d\n", ((A*)b)->vptr);((Vtable*)(b->a.vptr))->v1(); ((Vtable*)(b->a.vptr))->v2();((Vtable2*)(b->a.vptr))->p(); }int main() {test1();printf("---------------------------------------------\n\n");test2();printf("---------------------------------------------\n\n");test3();return 0; }/* **************************上面看著費勁----光看下面就行了 typedef struct {void(*v1)();void(*v2)(); }Vtable;Vtable A_Vtable = { &dong1, &dong2 };//如果不單獨測試A 這句話就是廢話typedef struct {//Vtable2有一個Vtable,所以Vtable2可以轉(zhuǎn)化為Vtable使用v1 v2。 Vtable vtable;//但是我們賦值的時候是Vtable2 所以真真調(diào)用的時候,還是從Vtable2中調(diào)用void(*p)(); }Vtable2;Vtable2 B_vtable = { { &dong11, &dong2 }, &dong66 };所以,至始至終我們利用的就是Vtable2指向的函數(shù)。可以調(diào)用v1那是因為Vtable2中有Vtable,而Vtable中有v1 */

總結(jié)

以上是生活随笔為你收集整理的C语言实现封装、继承、多态的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。