相對於C語言,C++對struct做了非常多的擴充,功能更全面了

我有相當長的一段時間(數月)沒有更新文章了。

並不是我放棄了寫技術文章,而是因為這段時間,我把精力主要放在了圖像智能算法的學習上了。去年12月時,我對圖像智能算法還懵懵懂懂,做著 Linux 嵌入式應用程序開發,現在我已經正式入職到算法公司了,收入翻了一番,哈哈,不過累了好多。廢話就到這裡,我的轉行辛酸史,以後再詳談。

相對於C語言,C++對struct做了非常多的擴充,功能更全面了

轉行啦

坦誠的說,就編程語言而言,因為一直在做 Linux 嵌入式程序開發的緣故,我對C語言更加了解一點,讀者應該能夠發現,我之前的大部分文章都是關於C語言的。不過現在做算法,C++更加適合。C++和C語言雖然很像,但是在細節上還是有所區別的。今天閱讀前輩同事的代碼時,注意到了 struct 關鍵字,這個關鍵字在C++中做了不少擴展。本文將嘗試做下總結。

C語言與C++中的struct

struct關鍵字是C語言中非常重要的關鍵字,在實際的C語言程序開發中,struct 不僅可以用於封裝各種複雜的數據結構,還能夠實現一些開發技巧——比如輔助數組賦值、模擬類等等,這些我之前的文章都討論過。C++不僅保留了C語言中 struct 的功能,還做了不少擴展,具體的可以通過下面這個表說明:

相對於C語言,C++對struct做了非常多的擴充,功能更全面了

struct在C語言和C++中的區別

請看下面這段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                                                                                             
void 

fun

(T num)

{ cout <

"num = "

<< num << endl; }

fun

(

1

)

;

fun

(

1.01

)

; /<code>

在一些開源工程中,我還發現過有使用 class 定義模板函數的,也即使用class替換typename關鍵字:

<code>template<

class

T

>

void

fun

(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 則更適合封裝對象。


分享到:


相關文章: