最近一段时间继续开始了c++的学习,作为c plus plus 难免会与c语言做一个对比,很明显的感受到c++语言注重代码的复用性和拓展性,而c语言更加注重其算法的高效性,这也是今后需要注意的地方,避免用c++语言写出c语言的思想,接下来就是正文
关于c++的语言特点:
- c++是一门面向对象的语言(很重要)
- 面向对象的三大特点(封装,继承,多态)
- c++库函数的头文件没有.h
- endl 换行并清空缓冲区
第一个,命名空间作用域
首先 :: 为作用域运算符(其中一个用法),在初写c++程序中有这样一段 using namespce std;也就是打开命名空间std ,有了这样一句话,才能使用标准库函数里的函数,其次,:: 前没有内容代表是全局的,
那么由此看来作用就如下,1. 确定了哪个命名空间下的哪个变量 2.区分系统函数和自定义函数
实例
1 #include<iostream> 2 using namespace std; 3 int nAge = 500; 4 namespace Bird 5 { 6 int nAge = 20; 7 } 8 namespace Person 9 { 10 int nAge = 100; 11 } 12 int main() 13 { 14 cout << Bird::nAge << endl; 15 cout << Person::nAge << endl; 16 cout << ::nAge << endl; 17 18 19 20 system("pause"); 21 return 0; 22 }
第二个,动态内存的分配与释放,静态内存和动态内存的区别就在于是不是在编译期系统自动分配内存,而动态内存的申请在c语言中是malloc函数,在c++中变为new函数,(而在源码中可以看到也是通过malloc去实现的)而new函数的参数列表不再是指定的大小,而是直接写类型就可以了,而同样是在堆区申请,得手动释放,就得用delete函数
实例
1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 int *p = new int; 6 cin >> *p; 7 cout << *p << endl; 8 9 int *arr = new int[]; 10 delete[] arr; 11 arr = NULL; 12 13 int *arr1 = new int(10); 14 cout << *arr1 << endl; 15 delete arr1; 16 arr1 = NULL; 17 18 struct Node 19 { 20 int i; 21 char b; 22 char c; 23 }; 24 Node *p = new Node; 25 delete p; 26 p = NULL; 27 28 33 system("pause"); 34 return 0; 35 }
第三个,范围for bool类型,首先c++可以在任意地方定义变量,不同于c语言只能在所用变量的上方定义变量,而我想说的范围for 是在c++新标准中定义的,可以实现自动遍历,但缺点是只能从头遍历,
而bool类型原来在c语言中并没有,是通过宏定义自己定义的,在c++中就规定了bool类型,区别于windows文件中的BOOL,其大小就不一样,BOOL为4个字节,bool为1个字节
实例
#include<iostream>using namespace std; int main() { int arr[10] = {0,1,2,3,4,5,6,7,8,9}; for(int nVal : arr) cout << nVal << endl; system("pause"); }
第四个,string 字符串类型,在c++中,关于字符串的使用无疑是大大方便了程序员,只要引用了<string>,拼接,判断,复制,只需要用 + == =来实现就可以
实例
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 int main() 5 { 6 string str = "aaa"; 7 str = "aaasssddd"; 8 cout << str << endl; 9 10 str += "wer"; 11 cout << str << endl; 12 13 if(str == "aaa") 14 cout << "YES!" << endl; 15 17 return 0; 18 system("pause"); 19 20 }
第四个,函数重载 ,函数默认参数,函数重载是指在同一个作用域,名字一样,参数列表不同的函数,那么在编写程序的时候即使函数名一致,而参数列表不用,在调用的时候,编译器会根据你在调用时的参数列表自己找到相应的函数,而默认参数是指,在声明函数的时候有些值先赋上,默认是从右向左,并且中间不能为空,传入时是从左向右,所以即使调用时不赋值,但是也必须从右向左按顺序
实例
1 #include<iostream> 2 using namespace std; 3 /*void Show(int a,int b); */ //重载函数 4 void Show(int a); 5 void Show(int a,int b,int c = 0,int d = 1); //重载默认参数从左向右进行设置默认参数 6 7 int main() 8 { 9 10 Show(1); 11 Show(2,3); 12 13 14 15 16 system("pause"); 17 return 0; 18 } 19 //void Show(int a,int b) 20 //{ 21 // cout << a * b << endl; 22 //} 23 void Show(int a) 24 { 25 cout << 3.14 * a << endl; 26 } 27 void Show(int a,int b,int c,int d) 28 { 29 cout << a << " " << b << " " << c << " " << d << endl; 30 }
第五个,引用,引用的作用定义两个变量指向同一个地址空间,相当于给变量起别名,但是定义引用必须进行初始化,并且,引用只能用一次如果用第二次的话就是赋值,最后引用的必须是一个合法的存储单元,像NULL就不可以进行引用,引用的符号是&,接下来利用引用来交换两个数的值
#include<iostream> using namespace std; void Swap(int &a,int &b); int main() { int a = 100; int b = 200; Swap(a,b); cout << a << " " << b << endl; system("pause"); return 0; } void Swap(int &a,int &b) { int Temp = NULL; Temp = a; a = b; b = Temp; }
第六个,函数的参数传递,函数的传递方式在c语言中说了两种,值传递,地址传递,在c++中加入一个引用传递,区别在于值传递改变不了传递的内容,但是其他两种可以,一个是通过地址进行修改,另一个是通过给一个变量起的别名进行修改,接下来可以尝试利用引用来进行链表添加
1 #include<iostream> 2 using namespace std; 3 struct Node 4 { 5 int id; 6 struct Node *next; 7 }; 8 void AddNode(Node **ppHead,Node **ppEnd,int id); 9 int main() 10 { 11 Node *pHead = NULL; 12 Node *pEnd = NULL; 13 14 15 16 17 system("pause"); 18 return 0; 19 } 20 void AddNode(Node **ppHead,Node **ppEnd,int id) 21 { 22 Node *pNode = new Node; 23 pNode->id = id; 24 pNode->next = NULL; 25 }
第七个 类 对象 ,这是c++学习中最重要和基础的部分,
类的关键字是class,其后加类名,类中可以装变量和函数,而通过类声明的变量叫做对象,在类中有三类访问修饰符:
- public 公共的,所有位置都可使用
- protected 受保护的,只有本类和派生类可以用
- private 只有本类可以使用
而类的定义方式和结构体很相似,结构体默认为public,类默认为private,先做一个小练习,定义一个雇员类
1 #include<iostream> 2 using namespace std; 3 class CEmployee 4 { 5 private: 6 int m_nAge; 7 int m_nYear; 8 int m_nMoney; 9 public: 10 void SetAge(int Age) 11 { 12 m_nAge = Age; 13 } 14 void SetYear(int Year) 15 { 16 m_nYear = Year; 17 } 18 void SetMoney(int Money) 19 { 20 m_nMoney = Money; 21 } 22 public: 23 int GetAge() 24 { 25 return m_nAge; 26 } 27 int GetYear() 28 { 29 return m_nYear; 30 } 31 int GetMoney() 32 { 33 return m_nMoney; 34 } 35 public: 36 void Show() 37 { 38 cout << m_nAge << endl; 39 cout << m_nYear << endl; 40 cout << m_nMoney << endl; 41 } 42 }; 43 using namespace std; 44 int main() 45 { 46 CEmployee ps1; 47 ps1.SetAge(20); 48 ps1.SetYear(10); 49 ps1.SetMoney(20000); 50 51 CEmployee ps2; 52 ps2.SetAge(25); 53 ps2.SetYear(2); 54 ps2.SetMoney(2000); 55 56 ps1.Show(); 57 ps2.Show(); 58 59 60 61 62 system("pause"); 63 return 0; 64 }
通过这段代码可以很清晰的看出什么是面向对象,在主函数中一切都是对象去调用函数,我们所注重的就是把对象这个类去完善,不知道大家有没有发现一个问题,在这个雇员类中的成员属性,是私有的,如何进行赋值和初始化呢,这个就需要介绍接口了,既然私有类只能在本类使用,那么我就在本类中定义一个公有的函数去初始化私有的属性,这个函数就叫接口,接口的形式有很多,但目的都是接通私有的,用户可以进行我规定的修改。
第八个,构造析构,在类中有一个特殊的函数,叫构造函数,它的名字同类名,并且没有返回值,之所以特殊是因为,在主函数创建对象的时候,构造函数自动调用,一般是用来给成员属性初始化使用,而析构函数,它的名字就是在类名前加一个取反~符,不允许赋参数,用来删除类内指针成员在堆区分配的空间,它也很特殊,在对象生命周期结束时,自动进行调用,非常重要的一点,构造函数可以有多个,但析构函数只能有一个,
实例
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class CPerson 5 { 6 public: 7 //-----------------------构造函数----------------------- 8 CPerson() 9 { 10 m_nAge = 1; 11 b_Sex = true; 12 str_Name = "bb"; 13 } 14 CPerson(string Name) 15 { 16 m_nAge = 1; 17 b_Sex = true; 18 str_Name = Name; 19 } 20 //-----------------------构造函数----------------------- 21 private: 22 int m_nAge; 23 bool b_Sex; 24 string str_Name; 25 public: 26 void Show() 27 { 28 cout << m_nAge << endl; 29 cout << b_Sex << endl; 30 cout << str_Name << endl; 31 } 32 public: 33 ~CPerson() 34 { 35 36 } 37 }; 38 39 int main() 40 { 41 CPerson ps; 42 ps.Show(); 43 44 CPerson ps1("cyc"); 45 ps1.Show(); 46 //CPerson ps1; 47 48 49 50 51 system("pause"); 52 return 0; 53 }
1 #include<iostream> 2 using namespace std; 3 class CPerson 4 { 5 private: 6 char *psz_Name; 7 public: 8 CPerson() 9 { 10 psz_Name = new char[10]; 11 strcpy_s(psz_Name,10,"cyc"); 12 } 13 //-----------------析构函数------------------------ 14 ~CPerson() 15 { 16 delete[] psz_Name; 17 psz_Name = NULL; 18 } 19 //-----------------析构函数------------------------ 20 public: 21 void Show() 22 { 23 cout << psz_Name << endl; 24 } 25 }; 26 27 int main() 28 { 29 CPerson ps; 30 ps.Show(); 31 32 33 system("pause"); 34 return 0; 35 }
针对以上,做了一个小练习,编写学生类的链表,首先需要认识的是,c++设计中的原则之一,单一职责(一个类中只装和这个类中有关的)目的是为了增加复用性,那么设计一个学生类,一个链表类就可以了,代码如下
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class CStudent 5 { 6 private: 7 string m_strName; 8 int m_nValue; 9 public: 10 CStudent() 11 { 12 m_strName = " "; 13 m_nValue = 0; 14 } 15 public: 16 void SetInfo(int id,string name) 17 { 18 m_nValue = id; 19 m_strName = name; 20 } 21 void Show() 22 { 23 cout << m_nValue << " " << m_strName << endl; 24 } 25 }; 26 27 28 29 30 class CList 31 { 32 private: //考虑类的时候,以对象的属性进行考虑,比如在链表中类的属性就包括长度,结点,头尾结点 33 struct Node 34 { 35 CStudent id; 36 struct Node *next; 37 }; 38 int m_nLen; 39 Node *m_pHead; 40 Node *m_pEnd; 41 public: 42 CList() 43 { 44 m_pHead = NULL; 45 m_pEnd = NULL; 46 m_nLen = 0; 47 } 48 ~CList() 49 { 50 while(m_pHead) 51 DeleteNode(); 52 } 53 public: 54 void AddNode(CStudent std) //在传参的时候,类的属性可以看作类内的全局变量,不用外部传入,比如人的年龄,在人这个类中就可以使用,不用外部进行传入 55 { 56 Node *pNode = new Node; 57 pNode->id = std; 58 pNode->next = NULL; 59 60 if(m_pHead == NULL) 61 { 62 m_pHead = pNode; 63 } 64 else 65 { 66 m_pEnd->next = pNode; 67 } 68 m_pEnd = pNode; 69 m_nLen++; 70 } 71 void DeleteNode() 72 { 73 if(m_pHead == NULL) 74 return; 75 if(m_nLen == 1) 76 { 77 m_pHead = NULL; 78 m_pEnd = NULL; 79 m_nLen = 0; 80 } 81 if(m_nLen > 1) 82 { 83 Node *pDel = NULL; 84 pDel = m_pHead; 85 m_pHead = m_pHead->next; 86 delete pDel; 87 pDel = NULL; 88 } 89 } 90 void Show() 91 { 92 Node *pMark = m_pHead; 93 while(pMark) 94 { 95 pMark->id.Show(); 96 pMark = pMark->next; 97 } 98 } 99 100 }; 101 int main() 102 { 103 CStudent std1; 104 std1.SetInfo(1,"cyc"); 105 CStudent std2; 106 std2.SetInfo(2,"xmx"); 107 CStudent std3; 108 std3.SetInfo(3,"wdh"); 109 CStudent std4; 110 std4.SetInfo(4,"pjh"); 111 112 113 CList list; 114 list.AddNode(std1); 115 list.AddNode(std2); 116 list.AddNode(std3); 117 list.AddNode(std4); 118 list.Show(); 119 system("pause"); 120 return 0; 121 }
第九个,对象的种类,做一个表格吧
对象种类 |
生命周期 |
|
1 |
栈区的局部对象 | 在声明的大括号结束时结束 |
2 |
堆区的指针对象 | 遇到delete结束 |
3 |
main函数外的全局对象 | 程序结束时结束 |
4 |
临时对象 | 当前一行结束时结束 |
前三个都很好理解,通过下断点调试就可以获得,而临时对象有很多种用法,其中一个用法就是作为一个临时变量存在,接着函数的返回值,
为什么c++中申请空间用new而不用malloc,其中最大的原因就是new可以出发构造和析构
第十个,this指针
在说this指针之前,首先要明白几件事,1. 空类的大小是1个字节,占位。2.成员变量,在创建对象的时候分配空间,而成员函数,编译的时候就放在代码区中,只有一份
那么问题就来了,既然成员函数只有一个,那多个对象调用同一个函数的时候,如何确定函数参数列表中的参数是属于哪个对象的成员变量的呢?
这里就涉及到了this指针,this指针存在于成员函数的参数列表之中,一般情况下是不显示的,用来装调用者对象的地址,这样就能连接类里变量和函数,写一个实例,用注释的方式把隐藏的部分写出来
this指针还有一个作用就是区分,成员函数使用的变量是全局的,还是类内的,类内就在对象前加this->
1 #include<iostream> 2 using namespace std; 3 int m_nAge = 0; 4 5 class CPerson 6 { 7 private: 8 int m_nAge; 9 public: 10 CPerson(int Age):m_nAge(Age) 11 { 12 13 } 14 public: 15 void Show(/*CPerson *this = &ps*/) 16 { 17 cout << ::m_nAge << endl; 18 cout << this->m_nAge << endl; 19 20 } 21 }; 22 23 int main() 24 { 25 CPerson ps(100); 26 cout << &ps << endl; 27 ps.Show(/*&ps*/); 28 29 30 system("pause"); 31 return 0; 32 }
第十一 const static
在介绍这两个关键字之前,先介绍初始化列表,初始化列表的结构 构造函数名:成员属性(初始化的值) ,如果有多个成员属性需要初始化的话,那么先定义的就先初始化,初始化顺序就是定义成员变量的顺序
而还有需要使用初始化列表的情况,就是一个对象在另一个类中使用,而这个对象作为另一个类的成员属性,需要初始化,此时的初始化就需要在初始化列表中初始化,举个例子吧
1 //----------------------------初始化列表的顺序------------------------------------ 2 #include<iostream> 3 using namespace std; 4 class CPerson 5 { 6 private: 7 int m_nAge; 8 int m_nSex; 9 public: 10 CPerson(int i):m_nAge(i),m_nSex(m_nAge) 11 { 12 cout << m_nAge << endl; 13 cout << m_nSex << endl; 14 } 15 16 }; 17 int main() 18 { 19 CPerson ps(100); 20 21 22 23 24 system("pause"); 25 return 0; 26 } 27 //----------------------------------在类中对其他对象初始化------------------------- 28 #include<iostream> 29 using namespace std; 30 class CChina 31 { 32 private: 33 int m_nAge; 34 public: 35 CChina(int a):m_nAge(a) 36 { 37 38 } 39 public: 40 void Show() 41 { 42 cout << m_nAge << endl; 43 } 44 45 }; 46 47 class CPerson 48 { 49 private: 50 CChina china; 51 public: 52 CPerson():china(123) //通过初始化列表给类中对象初始化 53 { 54 china.Show(); 55 } 56 57 }; 58 int main() 59 { 60 CPerson ps; 61 62 system("pause"); 63 return 0; 64 }
接下来就介绍关键字 const static 这两个在c语言中曾经介绍过,const 限定一个变量不允许被改变,static 则是声明了一个静态变量,先来列个表,展示一下两者在类中的区别
const |
static |
|
成员常变量/静态变量 |
只能在初始化列表中初始化 | 只能在类外进行初始化 |
常函数/静态函数 |
只能使用成员属性,不能修改 | 只能使用静态成员属性 |
常对象 |
只能使用常函数 |
1.static作为静态变量声明的关键字,也是类似于成员函数(可以声明后通过查看类的大小进行验证)在编译器就存在了,并且所有的对象共享,可以在类外直接初始化,也可以 类名::静态变量 进行初始化
2.静态函数之所以只能使用静态成员属性的本质原因:static函数没有this指针,无法确定使用的是哪个对象的,但是静态变量可以共享,所有静态函数可以无this指针的使用静态成员属性,如果自己实在想使用,也可以手动加一个this指针
3.const有一个特点就是定义就必须初始化,而且不可修改
4.常函数只能使用成员属性的本质原因:常函数的this指针也是const类型的,*this是不可修改的,这也解释了为什么常对象只能用常函数,因为常对象的类型是 const 类名 * 和常函数的指针类型相符,普通对象的类型是类名 *,安全性可以提升但不能减低。
1 #include<iostream> 2 using namespace std; 3 4 class CPerson 5 { 6 private: 7 const int m_nAge; 8 public: 9 CPerson():m_nAge(100) 10 { 11 12 } 13 public: 14 void Show(/*const CPerson *this = const CPerson * */) const 15 { 16 cout << m_nAge << endl; 17 } 18 void Showshow(/*CPerson *this = CPerson * */) //之所以常量对象不能调用常量函数就是因为 this指针的类型不符 19 { 20 cout << m_nAge << endl; 21 } 22 23 }; 24 int main() 25 { 26 const CPerson ps; 27 ps.Show(/*const CPerson * */); 28 // ps.Showshow(/*CPerson * */); 29 30 31 32 system("pause"); 33 return 0; 34 }
1 #include<iostream> 2 using namespace std; 3 4 class CPerson 5 { 6 public: 7 static int m_nAge; 8 int m_nSex; 9 public: 10 CPerson():m_nSex(500) 11 { 12 } 13 public: 14 static void Show() //本质在于函数列表内没有this指针,存储本对象的地址 15 { 16 cout << m_nAge << endl; 17 //cout << m_nSex << endl; 18 } 19 static void ShowShow(CPerson *pThis) //手动添加的可以使用非静态成员变量的静态成员函数 20 { 21 22 cout << pThis->m_nSex << endl; 23 } 24 25 }; 26 27 int CPerson::m_nAge = 100; 28 29 int main() 30 { 31 32 CPerson ps; 33 ps.ShowShow(&ps); 34 35 CPerson ps1; 36 CPerson::m_nAge = 200; 37 ps.Show(); 38 39 40 41 42 43 system("pause"); 44 return 0; 45 }
接下来就要研究 类之间的关系了,基础知识就介绍到这里了
2019-05-24 13:42:38 编程小菜鸟自我反思,大佬可以提出自己的意见和建议,谢谢!!!