我有相當長的一段時間(數月)沒有更新文章了。
並不是我放棄了寫技術文章,而是因為這段時間,我把精力主要放在了圖像智能算法的學習上了。去年12月時,我對圖像智能算法還懵懵懂懂,做著 Linux 嵌入式應用程序開發,現在我已經正式入職到算法公司了,收入翻了一番,哈哈,不過累了好多。廢話就到這裡,我的轉行辛酸史,以後再詳談。
坦誠的說,就編程語言而言,因為一直在做 Linux 嵌入式程序開發的緣故,我對C語言更加了解一點,讀者應該能夠發現,我之前的大部分文章都是關於C語言的。不過現在做算法,C++更加適合。C++和C語言雖然很像,但是在細節上還是有所區別的。今天閱讀前輩同事的代碼時,注意到了 struct 關鍵字,這個關鍵字在C++中做了不少擴展。本文將嘗試做下總結。
C語言與C++中的struct
struct關鍵字是C語言中非常重要的關鍵字,在實際的C語言程序開發中,struct 不僅可以用於封裝各種複雜的數據結構,還能夠實現一些開發技巧——比如輔助數組賦值、模擬類等等,這些我之前的文章都討論過。C++不僅保留了C語言中 struct 的功能,還做了不少擴展,具體的可以通過下面這個表說明:
請看下面這段C++代碼示例,我們首先使用 struct 定義了 S1,接著又定義了 S2,S2 繼承了 S1,因此我們可以在 test2 中使用 S1 中定義的成員 a、b。同時也可以看出,C++中的 struct 還可以定義成員函數,包括構造函數和析構函數。
<code>using
namespace
std
;struct
S1
{int
a;int
b; S1() { a =1
; b =2
; }void
print_mem
()
{cout
<"a = "
<< a <", b = "
<endl; } };struct
S2
: S1 {int
c; ~S2() {cout
<"S2 exit, c = "
<< c <endl
;cout
<"a = "
<< a <", b = "
<endl; } };int
main
()
{ S1 test1; test1.print_mem(); S2 test2; test2.a =3
; test2.b =4
; test2.c =5
;return
0
; }/<code>
編譯並執行上述C++代碼,不出意外地得到如下輸出:
<code>$
g++
t1.cpp
$
./a.out
a
=
1
,
b
=
2
S2
exit,
c
=
5
a
=
3
,
b
=
4
/<code>
C++ 中的 struct 和 class 關鍵字
從上面的例子不難看出,C++中的 struct 除了像C語言那樣可以定義數據結構外,還可以像 class 關鍵字那樣定義成員函數。不過,二者是有區別的。
成員的默認訪問控制屬性
首先,struct 默認的訪問控制屬性是 public,而 class 默認的訪問控制屬性是 private,這一點可以通過下面這段C++代碼示例看出:
<code>struct
A
{int
a; };class
B
{int
b; }; A ta; ta.a =1
; B tb; tb.b =2
; /<code>
繼承的默認訪問控制屬性
類似的,在繼承的過程中,struct 和 class 關鍵字的默認訪問控制屬性也是有所區別的:struct 默認 public,class 默認 private,例如下面這段C++ 代碼:
<code>struct
A
{int
a; };struct
B
: A {int
b; }; B tb; tb.a =1
; /<code>
這是沒有問題的,對象 tb 可以訪問由 A 繼承而來的成員 a。但是如果將 B 的 struct 改為 class,也即:
<code>struct
A
{int
a; };class
B
: A {int
b; }; B tb; tb.a =1
; /<code>
此時編譯就會報錯,提示“‘int A::a’ is inaccessible”,因為 class 的默認繼承屬性為 private。現在我們將 A 的 struct 修改為 class,B 的 class 再改回 struct,會發現,對象 tb 依然能夠正常訪問成員 a:
<code>class
A
{public
:int
a; };struct
B
: A {int
b; }; B tb; tb.a =1
; /<code>
應注意,這裡的討論重點是繼承的默認訪問控制屬性,因此我們將 A 中的 a 定義為 public 的。
可以看出,當 class 和 struct 混合使用時,默認的訪問控制屬性由子類決定,而不是由基類決定。不過,依賴默認屬性不是特別清晰的寫法,在實際的C++程序開發中,更推薦的做法是指明繼承的方式:
<code>class
B
:private
A { ... };class
B
:public
A { ... };/<code>
定義模板
相較於C語言,C++還能夠定義模板函數,請看下面這段代碼示例:
<code>template voidfun
(T num)
{ cout <"num = "
<< num << endl; }fun
(
1
);fun
(
1.01
); /<code>
在一些開源工程中,我還發現過有使用 class 定義模板函數的,也即使用class替換typename關鍵字:
<code>template<class
T
> voidfun
(T num)
{ cout <"num = "
<< num << endl; } /<code>
這種定義方式和上面使用typename的定義方式完全相同,但是 struct 就不能用於定義模板函數,如果讀者嘗試了,應該會得到編譯報錯的結果。
小結
本文先是討論了 struct 關鍵字在C語言和C++中的不同,不難發現,C++對 struct 關鍵字是做了不少擴充的,這些擴充讓 struct 看起來更像是 class 關鍵字。事實上,我認為就單純C++來說,class 關鍵字是完全可以取代 struct 的,C++ 仍然保留著 struct 關鍵字,其中一個重要原因就是兼容C語言。既然保留了 struct 關鍵字,總不能讓它完全等價於 class,因此二者在一些細節上有區別,這些輕微的區別往往能夠針對不同的需求提供不同的方便:struct 更適合封裝數據結構,class 則更適合封裝對象。