<C++> 类(1):定义 访问修饰符 相关函数(接口 构造 析构) 链表类(简单应用)
一.引入
在C中 有数据 函数 算法 那么在C++中 把这些东西封装到一起 就有了类 即class
C是面向过程 C++则是面向对象(但其实C++也不是纯面向对象的 是介于面向过程和面向对象之间的)
类 是一种抽象的数据类型 这个类型定义的变量 就叫对象
二.类
1.定义:类是一组相同的具有相同属性和行为的对象的抽象
对象是具体的 类则是抽象的
①例如:定义一个类CPerson
1 class CPerson 2 { 3 4 };
在定义一个类的时候 要注意里面变量的命名规范 这里暂时还没有体现
②调用对象:
1 CPerson cp;
2.访问修饰符:对类中东西(变量和函数)的访问权限
①public:公共的
在任何地方都可以看到
②protected:受保护的
只有自己(本类)和子类(派生类)可以使用 也就是继承 继承这个问题在后面会详细说
③private:私有的
只有自己可以用
注意:在结构体当中 默认的访问修饰符是public 但是在类中 默认的访问修饰符是private
访问修饰符的作用范围 就是到下一个访问修饰符 或是作用域结束(遇见“}”)
三.相关函数
1.接口函数:
①接口:可以按特定要求做修改 提供了和外部交互的通道 使内外部可以进行交互的操作
②接口函数的主要作用是:如果想在类以外的地方想拿到类中protected或private的变量 就可以定义一个接口函数
③例:
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 class CPerson 6 { 7 public: 8 int m_nAge; 9 protected: 10 bool m_nSex; 11 public: 12 string m_nName; 13 public: 14 void Show() 15 { 16 cout << m_nAge << endl; 17 cout << m_nSex << endl; 18 cout << m_nName << endl; 19 } 20 public: 21 int GetAge() 22 { 23 return m_nAge; 24 } 25 bool GetSex() 26 { 27 return m_nSex; 28 } 29 string GetName() 30 { 31 return m_nName; 32 } 33 public: 34 void SetAge(int nAge) 35 { 36 m_nAge = nAge; 37 } 38 void SetSex(bool nSex) 39 { 40 m_nSex = nSex; 41 } 42 void SetName(string nName) 43 { 44 m_nName = nName; 45 } 46 }; 47 48 int main() 49 { 50 CPerson pc; 51 52 pc.SetAge(0); 53 pc.SetSex(1); 54 pc.SetName("mby"); 55 56 cout << pc.GetAge() << endl; 57 cout << pc.GetSex() << endl; 58 cout << pc.GetName() << endl; 59 pc.Show(); 60 61 return 0; 62 }
这段代码中 就有典型的两种接口函数 一种是拿值 一种是可以改值的
2.构造函数:
①类当中的成员变量都是不允许直接初始化的 所以用一种函数 给他们初始化 这种函数就叫构造函数
②功能:初始化成员属性
③特点:
与类同名 无返回值
如果没自己定义 那么系统有默认的无参的构造函数
一旦定义构造函数系统就不会在调用默认的构造函数
注意:构造函数会在创建对象时自动调用 创建对象一定会调用构造函数
同一个类中构造函数可以写多个 根据所传的参数列表去执行
④例:
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 class CPerson 6 { 7 public: 8 int m_nAge; 9 bool m_nSex; 10 string m_nName; 11 public: 12 CPerson() 13 { 14 m_nAge = 1; 15 m_nSex = 1; 16 m_nName = "mby"; 17 } 18 CPerson(string nName) 19 { 20 m_nAge = 1; 21 m_nSex = 1; 22 m_nName = nName; 23 } 24 public: 25 void Show() 26 { 27 cout << m_nAge << endl; 28 cout << m_nSex << endl; 29 cout << m_nName << endl; 30 } 31 }; 32 33 int main() 34 { 35 CPerson pc1; 36 pc1.Show(); 37 38 CPerson pc2("MBY"); 39 pc2.Show(); 40 41 return 0; 42 }
3.析构函数:
①功能:删除类内的指针成员在堆区分配的空间 自动清理内存
注意:没有堆区成员就不用写析构函数 当有new或malloc的时候写就可以了
如果在类成员中有指针 那么构造函数中需要new空间 赋值用strcpy_s
②特点:
与类同名 前面加一个“~”
无返回值 无参数
析构函数一个类只能有一个 没写也会有默认的什么都不做的析构函数
③析构函数会在:当对象的声明周期结束的时候先调用析构函数 删除指针成员指向的空间 然后回收对象
4.总结:构造函数和析构函数
①构造和析构是相反的
②共同特点:自动调用(以防出现内存泄露的问题)
5.虚析构:
①引入:
普通函数的调用是看 调用指针的类型
虚函数的调用是看 虚函数列表中装的是谁
②实例:父类析构virtual ~CFather(){ .. }
父类析构的作用:在多态中 通过父类的指针删除一个子类的对象
其实正常大部分情况下 父类的析构都应该是虚析构
四.链表类
1.整个链表是一个对象 成员包括:结点 头指针 尾指针 长度
2.成员函数功能实现:构造 析构 尾插 头删 输出链表
3.封装的好处:提高了安全性 有利于后期修改 维护
那么所有的功能既然被封装到了一个类中 就要用对象去调用
4.代码:
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 class CList 6 { 7 private: 8 struct Node 9 { 10 int nValue; 11 Node* pNext; 12 }; 13 Node* m_pHead; 14 Node* m_pEnd; 15 int m_nSize; 16 public: 17 CList() 18 { 19 m_pHead = NULL; 20 m_pEnd = NULL; 21 m_nSize = NULL; 22 } 23 ~CList() 24 { 25 Node* pDel = 0; 26 while(m_pHead) 27 { 28 pDel = m_pHead; 29 m_pHead = m_pHead -> pNext; 30 delete pDel; 31 pDel = NULL; 32 } 33 m_pEnd = NULL; 34 m_nSize = 0; 35 } 36 public: 37 void PushBack(int nValue) 38 { 39 Node* pNode = new Node; 40 pNode -> nValue = nValue; 41 pNode -> pNext = NULL; 42 if(m_pHead == NULL) 43 { 44 m_pHead = pNode; 45 m_pEnd = pNode; 46 } 47 else 48 { 49 m_pEnd -> pNext = pNode; 50 m_pEnd = pNode; 51 } 52 ++ m_nSize; 53 } 54 void PopFront() 55 { 56 if(m_pHead == NULL) 57 { 58 return ; 59 } 60 if(m_pHead -> pNext == NULL) 61 { 62 delete m_pHead; 63 m_pHead = NULL; 64 m_pEnd = NULL; 65 m_nSize = 0; 66 } 67 68 Node* pDel = m_pHead; 69 m_pHead = m_pHead -> pNext; 70 delete pDel; 71 pDel = NULL; 72 -- m_nSize; 73 } 74 void Show() 75 { 76 Node* pMark = m_pHead; 77 while(pMark) 78 { 79 cout << pMark -> nValue << " "; 80 pMark = pMark -> pNext; 81 } 82 cout << "size:" << m_nSize << endl; 83 } 84 }; 85 86 int main() 87 { 88 89 CList a; 90 a.PushBack(1); 91 a.PushBack(2); 92 a.PushBack(3); 93 a.PushBack(4); 94 a.Show(); 95 96 a.PopFront(); 97 a.Show(); 98 99 return 0; 100 }
5.延伸:链表管理学生管理
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 class CStudent 6 { 7 private: 8 int m_nAge; 9 bool m_bSex; 10 string m_strName; 11 public: 12 CStudent() 13 { 14 m_nAge = 1; 15 m_bSex = true; 16 m_strName = "毛不易"; 17 } 18 public: 19 void SetStudentInfo(int nAge,bool bSex,string strName) 20 { 21 m_nAge = nAge; 22 m_bSex = bSex; 23 m_strName = strName; 24 } 25 void ShowStudentInfo() 26 { 27 cout << "Age:" << m_nAge << " Sex:" << m_bSex << " Name:" << m_strName << endl; 28 } 29 }; 30 31 class CList 32 { 33 private: 34 struct Node 35 { 36 CStudent nValue; 37 Node* pNext; 38 }; 39 Node* m_pHead; 40 Node* m_pEnd; 41 int m_nSize; 42 public: 43 CList() 44 { 45 m_pHead = NULL; 46 m_pEnd = NULL; 47 m_nSize = NULL; 48 } 49 ~CList() 50 { 51 Node* pDel = 0; 52 while(m_pHead) 53 { 54 pDel = m_pHead; 55 m_pHead = m_pHead -> pNext; 56 delete pDel; 57 pDel = NULL; 58 } 59 m_pEnd = NULL; 60 m_nSize = 0; 61 } 62 public: 63 void PushBack(CStudent& nValue) 64 { 65 Node* pNode = new Node; 66 pNode -> nValue = nValue; 67 pNode -> pNext = NULL; 68 if(m_pHead == NULL) 69 { 70 m_pHead = pNode; 71 m_pEnd = pNode; 72 } 73 else 74 { 75 m_pEnd -> pNext = pNode; 76 m_pEnd = pNode; 77 } 78 ++ m_nSize; 79 } 80 void PopFront() 81 { 82 if(m_pHead == NULL) 83 { 84 return ; 85 } 86 if(m_pHead -> pNext == NULL) 87 { 88 delete m_pHead; 89 m_pHead = NULL; 90 m_pEnd = NULL; 91 m_nSize = 0; 92 } 93 94 Node* pDel = m_pHead; 95 m_pHead = m_pHead -> pNext; 96 delete pDel; 97 pDel = NULL; 98 -- m_nSize; 99 } 100 void Show() 101 { 102 Node* pMark = m_pHead; 103 while(pMark) 104 { 105 pMark -> nValue.ShowStudentInfo(); 106 pMark = pMark -> pNext; 107 } 108 cout << "size:" << m_nSize << endl; 109 } 110 }; 111 112 int main() 113 { 114 CStudent st1; 115 st1.SetStudentInfo(1,true,"毛不易"); 116 CStudent st2; 117 st2.SetStudentInfo(2,true,"还是毛不易"); 118 119 CList a; 120 a.PushBack(st1); 121 a.PushBack(st2); 122 a.Show(); 123 124 a.PopFront(); 125 a.Show(); 126 127 return 0; 128 }