0%

Some thought about C/C++

前一陣子在做C++轉C Code的動作,真是麻煩的苦工。 在看到Modern C++ in embedded systems – Part 1: Myth and Reality還真是心有慼慼焉啊。C++能做的,C當然也可以,不過程式可讀性差很多,以下列出幾點。

Function overload

1
2
3
4
void Dosomething(int v);
void Dosomething(float v);
Dosomething(1);
Dosomething(3.14f);

這樣的Code在C++可行,在C會編譯失敗,因此要自行加上suffix錯開

1
2
3
4
void DosomethingWithInt(int v);
void DosomethingWithFloat(float v);
DosomethingWithInt(1);
DosomethingWithFloat(3.14f);

雖然效果是一樣的,不過人的記憶力是有限的,同時兩個淚名稱不同,功能相似的函式,有事沒事要分心注意,會殺死一堆腦細胞。
在C11之後,終於有了Generic Selections可用了。

1
2
3
4
5
define Dosomething(X) _Generic((X),  \
int: DosomethingWithInt, \
float: DosomethingWithFloat)(X)
Dosomething(1);
Dosomething(3.14f);

這下看起來好多了,不過如果每增加一種寒士,就要修改一次Dosomething的定義。還是很麻煩啊。這也無法解決所有問題。

Constructor & Destructor

在C++當中是

1
2
3
4
5
6
7
8
9
10
struct Obj {
Obj(int v);
~Obj();
};
int Doanotherthing(Obj *v);
nt Dosomething()
{
Obj local(10);
return Doanotherthing(&local);
}

同樣的Code在C與研究寫得支離破碎了

1
2
3
4
5
6
7
8
9
10
void init_Obj(Obj *this, int v) 
void uninit_Obj(Obj *this);
int Dosomething()
{
Obj local;
init_Obj(&local, 10);
int result = Doanotherthing(&local);
uninit_Obj(&local);
return result;
}

由於C不會主動去呼叫Destructor,因此要將計算的值存起來,所以要主動呼叫Destructor。
由於我們不能簡單的把Constructor和Destructor定義成inituninit就好,原因同上面的Function overload,只好加上自行的suffix避開這個問題。

Member function

雖然這兩樣寫差異無幾

1
2
3
Obj *obj;
obj->Dosomething(); // member function
Dosomething(obj); // pass object to function

萬一有個cstruct 也有Dosomething的函式怎麼辦

1
2
3
Obj2 *obj2;
obj2->Dosomething(); // member function
DosomethingWithObj2(obj2); // pass object to function

又回到老問題了,不能function overload就要手動繞過很多眉角。