如何用C實現C++類裡面的成員?

假設現在有一個非常簡單的C++類

class Person
{
public:
int age;
char name[20];
void Get_Val()
{
printf("Input your name: ");
scanf("%c", name);
printf("Input your age: ");
scanf("%d", age);
printf("%c %d
", name, age);
}
};

Person類裡面有兩個成員name和age。如果用C去模擬的話,如何實現對成員的引用,題主只想到了一個很糟糕的解決方案。

typedef struct _Person
{
int age;
char name;
void(*Get_Val)(struct _Person *that);
} Person;

void _Get_Val(Person *that)
{
printf("Input your name: ");
scanf("%c", that-&>name);
printf("Input your age: ");
scanf("%d", that-&>age);
printf("%c%d", that-&>name, that-&>age);
}

利益關係:學習8位機,想把自己寫的函數庫封裝起來


糟糕的地方在於你不應該把非虛函數變成Person的成員變數。通常來講是這麼寫的:

C++:

struct IBitch
{
int bitch = 0;
Bitch(int _bitch):bitch(_bitch){}
virtual ~IBitch() = default;
virtual int Bitch()const = 0;
};

struct Fuck : virtual IBitch
{
int fuck = 0;
Fuck(int _fuck):IBitch(100), fuck(_fuck)();
virtual ~Fuck()=default;
virtual int Bitch()const{ return fuck + bitch; }
};

struct Shit : virtual IBitch
{
int shit = 0;
Fuck(int _shit):IBitch(100), shit(_shit)();
virtual ~Shit()=default;
virtual int Bitch()const{ return shit + bitch; }
};

struct FuckShit : Fuck, Shit
{
FuckShit(int _fuck, int _shit):IBitch(100), Fuck(_fuck), Shit(_shit){}
virtual int Bitch()const{ return fuck + shit + bitch; }
}

int main()
{
const IBitch fuck = Fuck(1);
const IBitch shit = Shit(2);
const IBitch bitch = FuckShit(3, 4);
cout &<&< fuck.Bitch() &<&< "," &<&< shit.Bitch() &<&< "," &<&< bitch.Bitch() &<&< endl; return 0; }

C:無責任手寫請自行調試挑錯

// 偷懶去掉typedef不想遵守C語言語法

struct IBitch;
struct Fuck;
struct Shit;
struct FuckShit;

/***************************************************
IBitch
***************************************************/

struct vtable_IBitch
{
void(*__dtor)(IBitch*);
int(*Bitch)(IBitch*);
};

vtable_IBitch __vtable_IBitch_IBitch;

struct IBitch
{
vtable_IBitch* __vtable;
int bitch;
};

void __ctor_IBitch(IBitch* __this, int _bitch)
{
__this-&>__vtable = __vtable_IBitch_IBitch;
__this-&>bitch = _bitch;
}

void __dtor_IBitch(IBitch* __this)
{
}

void __virtual_dtor_IBitch(IBitch* __this)
{
__dtor_IBitch(__this);
}

/***************************************************
Fuck
***************************************************/

struct Fuck
{
IBitch* __base_IBitch;
int fuck;
};

struct __final_Fuck
{
Fuck __base_Fuck;
IBitch __base_Bitch;
};

vtable_IBitch __vtable___final_Fuck_IBitch;

void __ctor_Fuck(Fuck* __this, IBitch* __base_IBitch, int _fuck)
{
__this-&>__base_IBitch = __base_IBitch;
__this-&>fuck = _fuck;
}

void __dtor_Fuck(Fuck* __this)
{
}

void __ctor___final_Fuck(__final_Fuck* __this, int _fuck)
{
__ctor_IBitch(__this-&>__base_Bitch, 100);
__this-&>__base_Bitch.__vtable = __vtable___final_Fuck_IBitch;
__this-&>__base_Fuck.__base_IBitch = __this-&>__base_Bitch;
__ctor_Fuck(__this-&>__base_Fuck, __this-&>__base_Bitch, _fuck);
}

void __virtual_dtor___final_Fuck(IBitch* __this)
{
int offset = offsetof(__final_Fuck, __base_Bitch);
__final_Fuck* object = reinterpret_cast&<__final_Fuck*&>(reinterpret_cast&(__this) - offset);
__dtor_Fuck(object-&>__base_Fuck);
__dtor_IBitch(object-&>__base_Bitch);
}

int __member_Fuck_Bitch(Fuck* __this)
{
return __this-&>fuck + __this-&>__base_IBitch-&>bitch;
}

int __virtual___final_Fuck_Bitch(IBitch* __this)
{
int offset = offsetof(__final_Fuck, __base_Bitch);
__final_Fuck* object = reinterpret_cast&<__final_Fuck*&>(reinterpret_cast&(__this) - offset);
return __member_Fuck_Bitch(object-&>__base_Fuck);
}

/***************************************************
Shit
***************************************************/

struct Shit
{
IBitch* __base_IBitch;
int shit;
};

struct __final_Shit
{
Shit __base_Shit;
IBitch __base_Bitch;
};

vtable_IBitch __vtable___final_Shit_IBitch;

void __ctor_Shit(Shit* __this, IBitch* __base_IBitch, int _shit)
{
__this-&>__base_IBitch = __base_IBitch;
__this-&>shit = _shit;
}

void __dtor_Shit(Shit* __this)
{
}

void __ctor___final_Shit(__final_Shit* __this, int _shit)
{
__ctor_IBitch(__this-&>__base_Bitch, 100);
__this-&>__base_Bitch.__vtable = __vtable___final_Shit_IBitch;
__this-&>__base_Shit.__base_IBitch = __this-&>__base_Bitch;
__ctor_Shit(__this-&>__base_Shit, __this-&>__base_Bitch, _shit);
}

void __virtual_dtor___final_Shit(IBitch* __this)
{
int offset = offsetof(__final_Shit, __base_Bitch);
__final_Shit* object = reinterpret_cast&<__final_Shit*&>(reinterpret_cast&(__this) - offset);
__dtor_Shit(object-&>__base_Shit);
__dtor_IBitch(object-&>__base_Bitch);
}

int __member_Shit_Bitch(Shit* __this)
{
return __this-&>shit + __this-&>__base_IBitch-&>bitch;
}

int __virtual___final_Shit_Bitch(IBitch* __this)
{
int offset = offsetof(__final_Shit, __base_Bitch);
__final_Shit* object = reinterpret_cast&<__final_Shit*&>(reinterpret_cast&(__this) - offset);
return __member_Shit_Bitch(object-&>__base_Shit);
}

/***************************************************
FuckShit
***************************************************/

struct FuckShit
{
IBitch* __base_IBitch;
Fuck __base_Fuck;
Shit __base_Shit;
};

struct __final_FuckShit
{
FuckShit __base_FuckShit;
IBitch __base_Bitch;
};

vtable_IBitch __vtable___final_FuckShit_IBitch;

void __ctor_FuckShit(FuckShit* __this, IBitch* __base_IBitch, int _fuck, int _shit)
{
__this-&>__base_IBitch = __base_IBitch;
__ctor_Fuck(__this-&>__base_Fuck, __base_IBitch, _fuck);
__ctor_Shit(__this-&>__base_Shit, __base_IBitch, _shit);
}

void __dtor_FuckShit(FuckShit* __this)
{
__dtor_Fuck(__this-&>__base_Fuck);
__dtor_Shit(__this-&>__base_Shit);
}

void __ctor___final_FuckShit(__final_FuckShit* __this, int _fuck, int _shit)
{
__ctor_IBitch(__this-&>__base_Bitch, 100);
__this-&>__base_Bitch.__vtable = __vtable___final_FuckShit_IBitch;
__this-&>__base_FuckShit.__base_IBitch = __this-&>__base_Bitch;
__ctor_FuckShit(__this-&>__base_FuckShit, __this-&>__base_Bitch, _fuck, _shit);
}

void __virtual_dtor___final_FuckShit(IBitch* __this)
{
int offset = offsetof(__final_FuckShit, __base_Bitch);
__final_FuckShit* object = reinterpret_cast&<__final_FuckShit*&>(reinterpret_cast&(__this) - offset);
__dtor_FuckShit(object-&>__base_FuckShit);
__dtor_IBitch(object-&>__base_Bitch);
}

int __member_FuckShit_Bitch(FuckShit* __this)
{
return __this-&>__base_Fuck.fuck + __this-&>__base_Shit.shit + __this-&>__base_IBitch-&>bitch;
}

int __virtual___final_FuckShit_Bitch(IBitch* __this)
{
int offset = offsetof(__final_FuckShit, __base_Bitch);
__final_FuckShit* object = reinterpret_cast&<__final_FuckShit*&>(reinterpret_cast&(__this) - offset);
return __member_FuckShit_Bitch(object-&>__base_FuckShit);
}

/***************************************************
Config
***************************************************/

void Config()
{
__vtable_IBitch_IBitch.__dtor = __virtual_dtor_IBitch;
__vtable_IBitch_IBitch.Bitch = nullptr;

__vtable___final_Fuck_IBitch.__dtor = __virtual_dtor___final_Fuck;
__vtable___final_Fuck_IBitch.Bitch = __virtual___final_Fuck_Bitch;

__vtable___final_Shit_IBitch.__dtor = __virtual_dtor___final_Shit;
__vtable___final_Shit_IBitch.Bitch = __virtual___final_Shit_Bitch;

__vtable___final_FuckShit_IBitch.__dtor = __virtual_dtor___final_FuckShit;
__vtable___final_FuckShit_IBitch.Bitch = __virtual___final_FuckShit_Bitch;
}

/***************************************************
Main
***************************************************/

int main()
{
__final_Fuck __temp_fuck;
__final_Shit __temp_shit;
__final_FuckShit __temp_bitch;
IBitch* fuck;
IBitch* shit;
IBitch* bitch;
Config();

__ctor___final_Fuck(__temp_fuck, 1);
__ctor___final_Shit(__temp_shit, 2);
__ctor___final_FuckShit(__temp_bitch, 3, 4);
fuck = __temp_fuck.__base_Bitch;
shit = __temp_shit.__base_Bitch;
bitch = __temp_bitch.__base_Bitch;

cout &<&< fuck-&>__vtable-&>Bitch(fuck) &<&< "," &<&< shit-&>__vtable-&>Bitch(shit) &<&< "," &<&< bitch-&>__vtable-&>Bitch(bitch) &<&< endl; bitch-&>__vtable-&>__dtor(bitch);
shit-&>__vtable-&>__dtor(shit);
fuck-&>__vtable-&>__dtor(fuck);

return 0;
}

自行參考《深入探索C++對象模型》


……既然C不是OOP你就彆強求著用OO的方式來寫。就按照PO來寫,建個函數接受Person struct的指針就完了。別在struct裡面建函數指針,你又不是要寫虛函數。


你可以用GObject那一套。

GObject Reference Manual

動態特性比C++要徹底得多,就是宏有點噁心。


建議看一下glib源碼,裡面有用c實現類,繼承,介面等完整的方法。


有本書叫做 Object-Oriented Programming With ANSI-C


繼承通過指針就能模擬,也能大概實現公有私有,但實現不了友元,至於成員函數,個人認為(補充:你這樣子)把函數指針放結構體里是不妥的,函數重載也能模擬,只是太太太費勁。

大概功能模擬完了,剩下的就靠自己想像了,。

好了,這就是一個完美的類,是不!


普通成員方法用函數指針。虛成員方法自己實現虛表,具體可參考《深入探索C++對象模型》一書。


關鍵就是實現虛表


推薦閱讀:

socket拋出Cant assign requested address,問題所在以及解決方法?
C++序列化json字元串對Unicode有哪些特殊處理?
今天面試C++,機試面試官看完代碼說代碼結構混亂?
C++primer中一個疑似錯誤?
初學者學c++應該做什麼準備?

TAG:C編程語言 | 面向對象編程 | 單片機 | C | CC |