這里我想主要介紹下在C語(yǔ)言中是如何實(shí)現(xiàn)的面向?qū)ο?。知道了C語(yǔ)言實(shí)現(xiàn)面向?qū)ο蟮姆绞?,我們?cè)俾?lián)想下,C++中的class的運(yùn)行原理是什么?
首先我們來(lái)寫(xiě)一段C++的class,拿一個(gè)Student類(lèi)來(lái)舉例子:
在頭文件中,我定義一個(gè)Student類(lèi):
#pragma once class Student { public: void SetNumber(int number); void SetGrade(int grade); void Print(); private: int number; int grade; };
再在源文件中實(shí)現(xiàn)它:
#include "studentpp.h" #includevoid Student::SetNumber(int number) { this->number = number; } void Student::SetGrade(int grade) { this->grade = grade; } void Student::Print() { printf("studentpp number : %d, grade : %d ", this->number, this->grade);}
接下來(lái)是使用Student類(lèi):
#include#include "studentpp.h" int main() { Student *stu1 = new Student; Student *stu2 = new Student; stu1->SetNumber(11); stu2->SetNumber(22); stu1->SetGrade(111); stu2->SetGrade(222); stu1->Print(); stu2->Print(); delete stu1; delete stu2; }
我們?cè)龠\(yùn)行一下,運(yùn)行結(jié)果不出所料。
那你有沒(méi)有想過(guò),它的底層是怎么實(shí)現(xiàn)的?為什么不同對(duì)象,設(shè)置了不同的number和grade,它的輸出卻不一樣?
這個(gè)問(wèn)題我們先放在這。等我用C語(yǔ)言實(shí)現(xiàn)一套這種方案后,估計(jì)你就明白了。
首先,在頭文件中定義一個(gè)C語(yǔ)言的結(jié)構(gòu)體Student:
#pragma once typedef struct Student Student; Student* CreateStudent(); void DestroyStudent(Student* student); void SetNumber(Student* student, int number); void SetGrade(Student* student, int grade); void Print(Student* student);
注意在這里我使用了一個(gè)typedef,即Student = struct Student;
但是我卻沒(méi)有在頭文件中定義它:
struct Student { int number; int grade; };
我把它放在了源文件中,在源文件中定義它,再實(shí)現(xiàn)相關(guān)的方法。
#include "student.h" #include#include struct Student { int number; int grade; }; Student* CreateStudent() { Student* self = (Student*)malloc(sizeof(Student)); return self; } void DestroyStudent(Student* student) { if (!student) return; free((void*)student); } void SetNumber(Student* student, int number) { if (!student) return; student->number = number; } void SetGrade(Student* student, int grade) { if (!student) return; student->grade = grade; } void Print(Student* student) { if (!student) return; printf("student number : %d, grade : %d ", student->number, student->grade); }
然后使用它:
#include "student.h" int main() { Student* stu1 = CreateStudent(); Student* stu2 = CreateStudent(); SetNumber(stu1, 11); SetNumber(stu2, 22); SetGrade(stu1, 111); SetGrade(stu2, 222); Print(stu1); Print(stu2); DestroyStudent(stu1); DestroyStudent(stu2); }
這是不是面向?qū)ο蟮脑???shù)據(jù)封裝到了不同的指針下,不同的指針傳到了相同的函數(shù)中,行為也會(huì)不同。
這時(shí)候我們?cè)俾?lián)想一下C++中的面向?qū)ο笫遣灰彩沁@個(gè)原理:
平時(shí)我們使用的:
a->Print();
其實(shí)它的原理可能是這樣的:
void Print(Student* this) { this->number; this->grade; }
只不過(guò)編譯器把默認(rèn)的這個(gè)this參數(shù)隱藏在內(nèi)部,我們看不見(jiàn)而已。其實(shí)每個(gè)成員函數(shù)默認(rèn)都會(huì)有一個(gè)參數(shù),就是對(duì)象的指針,也就是this指針。到這里你應(yīng)該也就明白面向?qū)ο蟮脑砹税伞?/p>
注意在這里我使用了一個(gè)typedef,即Student = struct Student;
但是我卻沒(méi)有在頭文件中定義它。
這樣可以更好的隱藏Student的實(shí)現(xiàn),外面不知道Student究竟是什么東西,只有內(nèi)部知道。在頭文件中對(duì)外只暴露Student的指針,然后指針傳到源文件中,再去解析它。
比如,我在其它地方想要得到Student的大小,編譯器會(huì)報(bào)錯(cuò),沒(méi)法使用sizeof,因?yàn)樗恢繱tudent,它只知道它是不完整的類(lèi)型。而只能在源文件中使用sizeof。
這種設(shè)計(jì)是不是比C++的class更安全一些,確實(shí)安全,其實(shí)C++也可以這樣實(shí)現(xiàn),就是可以使用pImpl指針。
pimpl我暫時(shí)先不介紹,大家可以自己研究一下(其實(shí)歷史文章中介紹過(guò))。
大家可以思考下,怎么用C語(yǔ)言實(shí)現(xiàn)多態(tài)呢?
-
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136683 -
編譯器
+關(guān)注
關(guān)注
1文章
1623瀏覽量
49108 -
源文件
+關(guān)注
關(guān)注
0文章
30瀏覽量
4586
原文標(biāo)題:從C語(yǔ)言實(shí)現(xiàn)面向?qū)ο筇骄縞lass的秘密
文章出處:【微信號(hào):程序喵大人,微信公眾號(hào):程序喵大人】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論