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还有构造函数与析构函数,初始化工作与回收前的工作都会自动触发.

猜你喜欢

转载自blog.csdn.net/gz_sgkj/article/details/80539696