c++基礎知識:class與struct

C語言裏可用一個結構體來描述一種類型,如描述學生信息:

typedef struct {

char name[20];

int age;

int id;

}student_t;


如有三個學生,則:

student_t a, b, c;


通常情況下,用變量成員來描述類型的屬性,但是類型的行爲特徵應用函數來描述.在結構體只能加入函數指針變量成員來描述.


typedef struct {

char name[20];

int age;

int id;


void (*study)(intwhat);

void (*eat)(intwhat);

}student_t;


結構使用起來時比較麻煩,創建一個對象都需要初始化對象的函數指針變量成員.

而且,在結構體裏每個成員沒有分權限來限制訪問的,無法保證一些數據的完整性.


C++針對c的結構體引入類:

類裏面可以直接實現函數成員。

類裏面的成員可分權限:private protected public


1

2 #include<iostream>

3

4 using namespacestd;

5

6 class Student { // Student聲明後,直接使用Student就是表示類型

7 public: //聲明以下成員都是public的權限

8 string name; //注意:這裏僅僅是定義這個類型有哪些成員,並沒有分配具體的空間,所以這裏的成員不能賦初始值

9 int id;

10 int age;

11

12 voidstudy(int what) {

13 cout <<"study " << what << endl;

14 }

15

16 void eat(intwhat) {

17 cout <<"eat " << what << endl;

18 }

19 };

20

21 int main(void)

22 {

23 Student a,b; //創建對象ab,每個對象都有自己的屬性成員,但函數成員是共用的(通過查看對象的大小可知).函數成員裏不能寫死針對某個對象的操作,只寫要使用的成員名即可。

24

25 a.eat(888);

26 return 0;

27 }


public權限的成員,只要通過類的對象或者指向對象的指針變量都可以訪問.


private權限的成員,只能在類的內部或者友員訪問.如需改變類對象裏的private權限成員的值時,應通過public的函數成員來改變. private成員就是不希望被直接訪問的,訪問也只能通過public函數成員來訪問。

所以我們可以把一些數據隱藏起來,只在內部處理,別人無需訪問,這就是封裝。

1

2 #include<iostream>

3

4 using namespacestd;

5

6 class Student {

7 private:

8 string name;

9 int id;

10 int age;

11

12 public:

13 voidset_name(string n) {

14 name =n;

15 }

16

17 voidstudy(int what) {

18 cout <<name << " study " << what << endl;

19 }

20

21 };


22

23 int main(void)

24 {

25 Student a;

26

27 a.set_name("hehe");

28 a.study(23);

29

30

31 return 0;

32 }


私有成員也可以通過設置友員關係來訪問,但這種方式破壞了封裝性,儘量不要用.

1

2 #include<iostream>

3

4 using namespacestd;

5

6 class Student {

7 private:

8 string name;

9 int id;

10 int age;

11

12 public:

13 voidstudy(int what) {

14 cout <<name << " study " << what << endl;

15 }

16 friend intmain(void); //聲明main函數是Student類型的朋友

17 // friend classxx;

18 };

19

20 int main(void)

21 {

22 Student a;

23

24 a.name ="lilei";

25 a.study(23);

26

27

28 return 0;

29 }


protected權限的成員,具有private的權限外,還可以讓子類對象訪問(後面再具體實現).



c++類裏還可以有構造函數,析構函數。

構造函數在創建對象時自動被調用的,可用於初始對象裏的屬性成員的值

析構函數在回收對象時自動被調用的, 可用於對象回收前所需作的事情.


通常情況下構造函數成員是public的權限,某些場合可以是private的權限

析構函數都是public的權限


構造函數名與類名完全一致,沒有返回值,連void返回類型也不能寫。構造函數可重載.

析構函數名與類名一樣(前面多一個”~”符號),沒有返回值,析構函數不可重載.


1

2 #include<iostream>

3

4 using namespacestd;

5

6 class Student {

7 public:

8 Student() {

9 cout <<"student init" << endl;

10 }

11 ~Student() {

12 cout <<"student exit" << endl;

13 }

14 };

15

16 int main(void)

17 {

18 Student a;//如果是動態創建的對象需調用delete回收纔會觸發析構函數

19

20 cout <<"after object created" << endl;

21

22 return 0;

23 }


編譯執行後輸出:

[root@localhost06class]# ./a.out

student init

after object created

student exit



面試題,現有代碼如下:

int main(void)

{

cout <<“hello” << endl;

return 0;

}

要求不能改動main函數裏的代碼,實現在”hello”輸出前先輸出”nono”.

實現方法:創建一個全局類對象,觸發類的構造函數,構造函數裏輸出”nono”.


當自定義一個類型時,如沒有實現構造函數,編譯器會自動分配一個空的構造函數。

如果有實現構造函數,編譯器就不會再分配空的構造函數了.

1

2 #include<iostream>

3

4 using namespacestd;

5

6 class Student {

7 private:

8 string name;

9

10 public:

11 Student(string n) {

12 name =n;

13 }

14

15 voidstudy(string what) {

16 cout <<name << " study " << what << endl;

17 }

18 };

19

20 int main(void)

21 {

22 Student a; //這裏創建對象,需調用Student::Student()構造函數.通過錯誤信息也可以得知一個類也是一個名稱空間.也可以得知,創建對象生成的代碼裏會有類構造函數的調用.

//c++裏調用哪個函數,除了函數名以外,與函數參數個數,類型有關.

23

24

25 return 0;

26 }


編譯輸出:

[root@localhost06class]# g++ 04contructor.cpp

04contructor.cpp: Infunction ‘int main()’:

04contructor.cpp:22:10:error: no matching function for call to ‘Student::Student()

Student a;

^

04contructor.cpp:22:10:note: candidates are:

04contructor.cpp:11:2:note: Student::Student(std::string)

Student(string n){

^

04contructor.cpp:11:2:note: candidate expects 1 argument, 0 provided

04contructor.cpp:6:7:note: Student::Student(const Student&)

class Student {

^

04contructor.cpp:6:7:note: candidate expects 1 argument, 0 provided



可修改爲:

1

2 #include<iostream>

3

4 using namespacestd;

5

6 class Student {

7 private:

8 string name;

9

10 public:

11 Student(string n);

12 voidstudy(string what);

13 };

14

15 int main(void)

16 {

17 Studenta("superman"); // Student::Student(string)

18

19 a.study("Chinese");

20 return 0;

21 }

22

23Student::Student(string n)

24 {

25 name = n;

26 }

27

28 voidStudent::study(string what)

29 {

30 cout <<name << " study " << what << endl;

31 }

32


把雙向循環鏈表封裝成隊列的例子.

1

2 #include<iostream>

3

4 using namespacestd;

5

6//定義節點類型,隊列裏裝載多個節點對象

7 class Node {

8 public:

9 void *data;//裝數據的地址

10 Node *prev,*next;

11

12 Node(Node*n1 = NULL, Node *n2 = NULL) {

13 //創建對象時,兩個指針初始化爲傳進來的值,如不傳則設NULL

14 prev =n1;

15 next =n2;

16 }

17 };

18

19 //定義對列類型

20 class MyQueue {

21 private:

22 Node *head;//鏈表頭節點,只在內部使用

23

24 public:

25 MyQueue();

26 ~MyQueue();

27

28 intenqueue(void *data); //隊列的入隊函數

29 void*dequeue(); //隊列的出隊函數

30 };

31

32 int main(void)

33 {

34 MyQueue a,b; //每個對象就是一個隊列,不同的隊列可裝載不同類型的數據.重用起來就很方便了.

35 int *p;

36

37 a.enqueue(new int(22));

38 a.enqueue(new int(33));

39 a.enqueue(new int(44));

40 a.enqueue(new int(55));

41

42

43 while (p =(int *)a.dequeue())

44 cout <<*p << endl;

45

46

47

48 return 0;

49 }

50

51 void*MyQueue::dequeue()

52 {

53 Node *n;

54 void *data;

55

56 //把鏈表頭節點移除出隊列,交返回數據的地址

57 if(head->next == head)

58 returnNULL; //鏈表裏沒有節點

59

60 n =head->next;

61

62 head->next= n->next;

63 n->next->prev = head;

64 data =n->data;

65 delete n;

66 return data;

67 }

68

69 intMyQueue::enqueue(void *data)

70 {

71 Node *n;

72 //創建一個鏈表的節點對象,初始化後加入鏈表的尾部

73

74 n = newNode;

75 if (NULL ==n)

76 return-1;

77 n->data =data;

78 n->next =head;

79 n->prev =head->prev;

80

81 head->prev->next = n;

82 head->prev= n;

83 return 0;

84 }

85

86

87MyQueue::MyQueue()

88 {

89 //初始化鏈表頭節點,讓頭節點的prev,next指針指向自己本身

90 head = newNode;

91

92 head->prev= head;

93 head->next= head;

94 }

95

96

97MyQueue::~MyQueue()

98 {

99 Node *tmp,*tmp2;

100 //隊列回收前,把所有鏈表的節點空間回收

101 for (tmp =head->next; tmp != head;)

102 {

103 tmp->prev->next = tmp->next;

104 tmp->next->prev = tmp->prev;

105 tmp2 =tmp->next;

106 delete(char *)tmp->data;

107 deletetmp;

108 tmp =tmp2;

109 }

110

111 delete head;

112 }


總結下C++classCstruct方便的特點:

1.class的成員可分成不同權限,可控制哪些成員是被別人訪問的,哪些成員僅僅是內部使用.

struct的成員沒有分權限的,只可以訪問.


2.class可以直接寫函數成員,這樣更加直觀地描述一種類型包括它的行爲.

struct不可以直接寫函數成員,只可以寫函數指針成員,而且在使用函數指針成員前必須初始化指向一個有效的函數.


3.class裏的函數成員的參數在使用類內部的屬性成員時,不需要傳遞。在函數成員裏可以直接訪問類內部的屬性成員.


4.class還有構造函數與析構函數,初始化工作與回收前的工作都會自動觸發.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章