初始C++
注釋
變量
常量
關鍵字
標識符命名規則
數據類型
C++規定在創建一個變量或者常量時,必須要指定出相應的數據類型,否則無法給變量分配內存
整型
sizeof關鍵字
浮點型(實型)
有效位數保留七位,帶小數點。
這個是保留有效數字位數,不包括小數點。
字符型
轉義字符
字符串型
布爾類型 bool
數據的輸入
運算符
算術運算符
賦值運算符
比較運算符
邏輯運算符
程序流程結構
選擇結構
if語句
int main() {int score = 0;cout << "請輸入考試分數:" << endl;cin >> score;if (score > 600){cout << "我考上了一本大學" << endl;if (score > 700){cout << "我考上了北大" << endl;}else if (score > 650){cout << "我考上了清華" << endl;}else{cout << "我考上了人大" << endl;}}else if (score > 500){cout << "我考上了二本大學" << endl;}else if (score > 400){cout << "我考上了三本大學" << endl;}else{cout << "我未考上本科" << endl;}system("pause");return 0;
}
三目運算符
switch語句
循環結構
while循環語句
do...while循環語句
for循環語句
嵌套循環
跳轉語句
break語句
continue語句
goto語句
數組
一維數組
冒泡排序
二維數組
函數
函數的定義
函數的調用
值傳遞
函數的常見樣式
函數的聲明
函數的分文件編寫
指針
指針的定義和使用
每次p的地址是不一樣的。
指針所占內存空間
空指針和野指針
const 修飾指針
指針和數組
指針和函數
指針 數組 函數
//冒泡排序函數
void bubbleSort(int * arr, int len) //int * arr 也可以寫為int arr[]
{for (int i = 0; i < len - 1; i++){for (int j = 0; j < len - 1 - i; j++){if (arr[j] > arr[j + 1]){int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}//打印數組函數
void printArray(int arr[], int len)
{for (int i = 0; i < len; i++){cout << arr[i] << endl;}
}int main() {int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };int len = sizeof(arr) / sizeof(int);bubbleSort(arr, len);printArray(arr, len);system("pause");return 0;
}
結構體
結構體的定義和使用
//結構體定義
struct student
{//成員列表string name; //姓名int age; //年齡int score; //分數
}stu3; //結構體變量創建方式3 int main() {//結構體變量創建方式1struct student stu1; //struct 關鍵字可以省略stu1.name = "張三";stu1.age = 18;stu1.score = 100;cout << "姓名:" << stu1.name << " 年齡:" << stu1.age << " 分數:" << stu1.score << endl;//結構體變量創建方式2struct student stu2 = { "李四",19,60 };cout << "姓名:" << stu2.name << " 年齡:" << stu2.age << " 分數:" << stu2.score << endl;stu3.name = "王五";stu3.age = 18;stu3.score = 80;cout << "姓名:" << stu3.name << " 年齡:" << stu3.age << " 分數:" << stu3.score << endl;system("pause");return 0;
}
結構體數組
結構體指針
結構體嵌套結構體
//學生結構體定義
struct student
{//成員列表string name; //姓名int age; //年齡int score; //分數
};//教師結構體定義
struct teacher
{//成員列表int id; //職工編號string name; //教師姓名int age; //教師年齡struct student stu; //子結構體 學生
};int main() {struct teacher t1;t1.id = 10000;t1.name = "老王";t1.age = 40;t1.stu.name = "張三";t1.stu.age = 18;t1.stu.score = 100;cout << "教師 職工編號: " << t1.id << " 姓名: " << t1.name << " 年齡: " << t1.age << endl;cout << "輔導學員 姓名: " << t1.stu.name << " 年齡:" << t1.stu.age << " 考試分數: " << t1.stu.score << endl;system("pause");return 0;
}
結構體做函數參數
//學生結構體定義
struct student
{//成員列表string name; //姓名int age; //年齡int score; //分數
};//值傳遞
void printStudent(student stu )
{stu.age = 28;cout << "子函數中 姓名:" << stu.name << " 年齡: " << stu.age << " 分數:" << stu.score << endl;
}//地址傳遞
void printStudent2(student *stu)
{stu->age = 28;cout << "子函數中 姓名:" << stu->name << " 年齡: " << stu->age << " 分數:" << stu->score << endl;
}int main() {student stu = { "張三",18,100};//值傳遞printStudent(stu);cout << "主函數中 姓名:" << stu.name << " 年齡: " << stu.age << " 分數:" << stu.score << endl;cout << endl;//地址傳遞printStudent2(&stu);cout << "主函數中 姓名:" << stu.name << " 年齡: " << stu.age << " 分數:" << stu.score << endl;system("pause");return 0;
}
結構體中const使用場景
內存分區模型
程序運行前
程序運行后
new操作符
下面實例函數中,new 返回的是該數據類型的指針。所以用 int * 來接收。
引用
引用的基本使用
引用的注意事項
引用做函數參數
//1. 值傳遞
void mySwap01(int a, int b) {int temp = a;a = b;b = temp;
}//2. 地址傳遞
void mySwap02(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}//3. 引用傳遞
void mySwap03(int& a, int& b) {int temp = a;a = b;b = temp;
}int main() {int a = 10;int b = 20;mySwap01(a, b);cout << "a:" << a << " b:" << b << endl;mySwap02(&a, &b);cout << "a:" << a << " b:" << b << endl;mySwap03(a, b);cout << "a:" << a << " b:" << b << endl;system("pause");return 0;
}
引用做函數的返回值
//返回局部變量引用
int& test01() {int a = 10; //局部變量return a;
}//返回靜態變量引用
int& test02() {static int a = 20;return a;
}int main() {//不能返回局部變量的引用int& ref = test01();cout << "ref = " << ref << endl;cout << "ref = " << ref << endl;//如果函數做左值,那么必須返回引用int& ref2 = test02();cout << "ref2 = " << ref2 << endl;cout << "ref2 = " << ref2 << endl;test02() = 1000;cout << "ref2 = " << ref2 << endl;cout << "ref2 = " << ref2 << endl;system("pause");return 0;
}
引用的本質
常量引用
函數提高
函數默認參數
如果我們自己傳入了數據,就有自己的數據,如果沒有,就用默認值。
函數如果有聲明默認值,那么函數的實現就不能有,聲明和實現只能有一個默認參數。例如 1、2
函數占位參數
函數重載
函數重載碰到默認參數,會出現二義性,報錯,盡量避免這種情況。
//函數重載需要函數都在同一個作用域下
void func()
{cout << "func 的調用!" << endl;
}
void func(int a)
{cout << "func (int a) 的調用!" << endl;
}
void func(double a)
{cout << "func (double a)的調用!" << endl;
}
void func(int a ,double b)
{cout << "func (int a ,double b) 的調用!" << endl;
}
void func(double a ,int b)
{cout << "func (double a ,int b)的調用!" << endl;
}//函數返回值不可以作為函數重載條件
//int func(double a, int b)
//{
// cout << "func (double a ,int b)的調用!" << endl;
//}int main() {func();func(10);func(3.14);func(10,3.14);func(3.14 , 10);system("pause");return 0;
}
函數重載碰到默認參數,會出現二義性,報錯,盡量避免這種情況。
//函數重載注意事項
//1、引用作為重載條件void func(int &a)
{cout << "func (int &a) 調用 " << endl;
}void func(const int &a)
{cout << "func (const int &a) 調用 " << endl;
}//2、函數重載碰到函數默認參數void func2(int a, int b = 10)
{cout << "func2(int a, int b = 10) 調用" << endl;
}void func2(int a)
{cout << "func2(int a) 調用" << endl;
}int main() {int a = 10;func(a); //調用無constfunc(10);//調用有const//func2(10); //碰到默認參數產生歧義,需要避免system("pause");return 0;
}
類和對象
封裝
//圓周率
const double PI = 3.14;//1、封裝的意義
//將屬性和行為作為一個整體,用來表現生活中的事物//封裝一個圓類,求圓的周長
//class代表設計一個類,后面跟著的是類名
class Circle
{
public: //訪問權限 公共的權限//屬性int m_r;//半徑//行為//獲取到圓的周長double calculateZC(){//2 * pi * r//獲取圓的周長return 2 * PI * m_r;}
};int main() {//通過圓類,創建圓的對象// c1就是一個具體的圓Circle c1;c1.m_r = 10; //給圓對象的半徑 進行賦值操作//2 * pi * 10 = = 62.8cout << "圓的周長為: " << c1.calculateZC() << endl;system("pause");return 0;
}
//學生類
class Student {
public:void setName(string name) {m_name = name;}void setID(int id) {m_id = id;}void showStudent() {cout << "name:" << m_name << " ID:" << m_id << endl;}
public:string m_name;int m_id;
};int main() {Student stu;stu.setName("德瑪西亞");stu.setID(250);stu.showStudent();system("pause");return 0;
}
#include<iostream>
#include<iomanip>
#include<string>
using namespace std;
class student{
public:int xuehao;string name;void showname(){cout<<name<<endl;}void showxuehao(){cout<<xuehao<<endl;}
};
int main(){student s={11,"sjsk"};s.name="zhangsan";s.showname();s.showxuehao();return 0;
}
//三種權限
//公共權限 public 類內可以訪問 類外可以訪問
//保護權限 protected 類內可以訪問 類外不可以訪問
//私有權限 private 類內可以訪問 類外不可以訪問class Person
{//姓名 公共權限
public:string m_Name;//汽車 保護權限
protected:string m_Car;//銀行卡密碼 私有權限
private:int m_Password;public:void func(){m_Name = "張三";m_Car = "拖拉機";m_Password = 123456;}
};int main() {Person p;p.m_Name = "李四";//p.m_Car = "奔馳"; //保護權限類外訪問不到//p.m_Password = 123; //私有權限類外訪問不到system("pause");return 0;
}
struct和class區別
class C1
{int m_A; //默認是私有權限
};struct C2
{int m_A; //默認是公共權限
};int main() {C1 c1;c1.m_A = 10; //錯誤,訪問權限是私有C2 c2;c2.m_A = 10; //正確,訪問權限是公共system("pause");return 0;
}
成員屬性設置私有
class Person {
public://姓名設置可讀可寫void setName(string name) {m_Name = name;}string getName(){return m_Name;}//獲取年齡 int getAge() {return m_Age;}//設置年齡void setAge(int age) {if (age < 0 || age > 150) {cout << "你個老妖精!" << endl;return;}m_Age = age;}//情人設置為只寫void setLover(string lover) {m_Lover = lover;}private:string m_Name; //可讀可寫 姓名int m_Age; //只讀 年齡string m_Lover; //只寫 情人
};int main() {Person p;//姓名設置p.setName("張三");cout << "姓名: " << p.getName() << endl;//年齡設置p.setAge(50);cout << "年齡: " << p.getAge() << endl;//情人設置p.setLover("蒼井");//cout << "情人: " << p.m_Lover << endl; //只寫屬性,不可以讀取system("pause");return 0;
}
對象的初始化和清理
構造函數和析構函數
class Person
{
public://構造函數Person(){cout << "Person的構造函數調用" << endl;}//析構函數~Person(){cout << "Person的析構函數調用" << endl;}};void test01()
{Person p;
}int main() {test01();system("pause");return 0;
}
構造函數的分類及調用
//1、構造函數分類
// 按照參數分類分為 有參和無參構造 無參又稱為默認構造函數
// 按照類型分類分為 普通構造和拷貝構造class Person {
public://無參(默認)構造函數Person() {cout << "無參構造函數!" << endl;}//有參構造函數Person(int a) {age = a;cout << "有參構造函數!" << endl;}//拷貝構造函數Person(const Person& p) {age = p.age;cout << "拷貝構造函數!" << endl;}//析構函數~Person() {cout << "析構函數!" << endl;}
public:int age;
};//2、構造函數的調用
//調用無參構造函數
void test01() {Person p; //調用無參構造函數
}//調用有參的構造函數
void test02() {//2.1 括號法,常用Person p1(10);//注意1:調用無參構造函數不能加括號,如果加了編譯器認為這是一個函數聲明//Person p2();//2.2 顯式法Person p2 = Person(10); Person p3 = Person(p2);//Person(10)單獨寫就是匿名對象 當前行結束之后,馬上析構//2.3 隱式轉換法Person p4 = 10; // Person p4 = Person(10); Person p5 = p4; // Person p5 = Person(p4); //注意2:不能利用 拷貝構造函數 初始化匿名對象 編譯器認為是對象聲明//Person p5(p4);
}int main() {test01();//test02();system("pause");return 0;
}
拷貝構造函數調用時機
class Person {
public:Person() {cout << "無參構造函數!" << endl;mAge = 0;}Person(int age) {cout << "有參構造函數!" << endl;mAge = age;}Person(const Person& p) {cout << "拷貝構造函數!" << endl;mAge = p.mAge;}//析構函數在釋放內存之前調用~Person() {cout << "析構函數!" << endl;}
public:int mAge;
};//1. 使用一個已經創建完畢的對象來初始化一個新對象
void test01() {Person man(100); //p對象已經創建完畢Person newman(man); //調用拷貝構造函數Person newman2 = man; //拷貝構造//Person newman3;//newman3 = man; //不是調用拷貝構造函數,賦值操作
}//2. 值傳遞的方式給函數參數傳值
//相當于Person p1 = p;
void doWork(Person p1) {}
void test02() {Person p; //無參構造函數doWork(p);
}//3. 以值方式返回局部對象
Person doWork2()
{Person p1;cout << (int *)&p1 << endl;return p1;
}void test03()
{Person p = doWork2();cout << (int *)&p << endl;
}int main() {//test01();//test02();test03();system("pause");return 0;
}
構造函數調用規則
class Person {
public://無參(默認)構造函數Person() {cout << "無參構造函數!" << endl;}//有參構造函數Person(int a) {age = a;cout << "有參構造函數!" << endl;}//拷貝構造函數Person(const Person& p) {age = p.age;cout << "拷貝構造函數!" << endl;}//析構函數~Person() {cout << "析構函數!" << endl;}
public:int age;
};void test01()
{Person p1(18);//如果不寫拷貝構造,編譯器會自動添加拷貝構造,并且做淺拷貝操作Person p2(p1);cout << "p2的年齡為: " << p2.age << endl;
}void test02()
{//如果用戶提供有參構造,編譯器不會提供默認構造,會提供拷貝構造Person p1; //此時如果用戶自己沒有提供默認構造,會出錯Person p2(10); //用戶提供的有參Person p3(p2); //此時如果用戶沒有提供拷貝構造,編譯器會提供//如果用戶提供拷貝構造,編譯器不會提供其他構造函數Person p4; //此時如果用戶自己沒有提供默認構造,會出錯Person p5(10); //此時如果用戶自己沒有提供有參,會出錯Person p6(p5); //用戶自己提供拷貝構造
}int main() {test01();system("pause");return 0;
}
深拷貝與淺拷貝
class Person {
public://無參(默認)構造函數Person() {cout << "無參構造函數!" << endl;}//有參構造函數Person(int age ,int height) {cout << "有參構造函數!" << endl;m_age = age;m_height = new int(height);}//拷貝構造函數 Person(const Person& p) {cout << "拷貝構造函數!" << endl;//如果不利用深拷貝在堆區創建新內存,會導致淺拷貝帶來的重復釋放堆區問題m_age = p.m_age;m_height = new int(*p.m_height);}//析構函數~Person() {cout << "析構函數!" << endl;if (m_height != NULL){delete m_height;}}
public:int m_age;int* m_height;
};void test01()
{Person p1(18, 180);Person p2(p1);cout << "p1的年齡: " << p1.m_age << " 身高: " << *p1.m_height << endl;cout << "p2的年齡: " << p2.m_age << " 身高: " << *p2.m_height << endl;
}int main() {test01();system("pause");return 0;
}
初始化列表
class Person {
public:傳統方式初始化//Person(int a, int b, int c) {// m_A = a;// m_B = b;// m_C = c;//}//初始化列表方式初始化Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c) {}void PrintPerson() {cout << "mA:" << m_A << endl;cout << "mB:" << m_B << endl;cout << "mC:" << m_C << endl;}
private:int m_A;int m_B;int m_C;
};int main() {Person p(1, 2, 3);p.PrintPerson();system("pause");return 0;
}
類對象作為類成員
class Phone
{
public:Phone(string name){m_PhoneName = name;cout << "Phone構造" << endl;}~Phone(){cout << "Phone析構" << endl;}string m_PhoneName;};class Person
{
public://初始化列表可以告訴編譯器調用哪一個構造函數Person(string name, string pName) :m_Name(name), m_Phone(pName){cout << "Person構造" << endl;}~Person(){cout << "Person析構" << endl;}void playGame(){cout << m_Name << " 使用" << m_Phone.m_PhoneName << " 牌手機! " << endl;}string m_Name;Phone m_Phone;};
void test01()
{//當類中成員是其他類對象時,我們稱該成員為 對象成員//構造的順序是 :先調用對象成員的構造,再調用本類構造//析構順序與構造相反Person p("張三" , "蘋果X");p.playGame();}int main() {test01();system("pause");return 0;
}
靜態成員
class Person
{public:static int m_A; //靜態成員變量//靜態成員變量特點://1 在編譯階段分配內存//2 類內聲明,類外初始化//3 所有對象共享同一份數據private:static int m_B; //靜態成員變量也是有訪問權限的
};
int Person::m_A = 10;
int Person::m_B = 10;void test01()
{//靜態成員變量兩種訪問方式//1、通過對象Person p1;p1.m_A = 100;cout << "p1.m_A = " << p1.m_A << endl;Person p2;p2.m_A = 200;cout << "p1.m_A = " << p1.m_A << endl; //共享同一份數據cout << "p2.m_A = " << p2.m_A << endl;//2、通過類名cout << "m_A = " << Person::m_A << endl;//cout << "m_B = " << Person::m_B << endl; //私有權限訪問不到
}int main() {test01();system("pause");return 0;
}
class Person
{public://靜態成員函數特點://1 程序共享一個函數//2 靜態成員函數只能訪問靜態成員變量static void func(){cout << "func調用" << endl;m_A = 100;//m_B = 100; //錯誤,不可以訪問非靜態成員變量}static int m_A; //靜態成員變量int m_B; //
private://靜態成員函數也是有訪問權限的static void func2(){cout << "func2調用" << endl;}
};
int Person::m_A = 10;void test01()
{//靜態成員變量兩種訪問方式//1、通過對象Person p1;p1.func();//2、通過類名Person::func();//Person::func2(); //私有權限訪問不到
}int main() {test01();system("pause");return 0;
}
C++對象模型和this指針
成員變量和成員函數分開存儲
this指針概念
class Person
{
public:Person(int age){//1、當形參和成員變量同名時,可用this指針來區分this->age = age;}Person& PersonAddPerson(Person p){this->age += p.age;//返回對象本身return *this;}int age;
};void test01()
{Person p1(10);cout << "p1.age = " << p1.age << endl;Person p2(10);p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1);cout << "p2.age = " << p2.age << endl;
}int main() {test01();system("pause");return 0;
}
空指針訪問成員函數
//空指針訪問成員函數
class Person {
public:void ShowClassName() {cout << "我是Person類!" << endl;}void ShowPerson() {if (this == NULL) {return;}cout << mAge << endl;}public:int mAge;
};void test01()
{Person * p = NULL;p->ShowClassName(); //空指針,可以調用成員函數p->ShowPerson(); //但是如果成員函數中用到了this指針,就不可以了
}int main() {test01();system("pause");return 0;
}
const修飾成員函數
class Person {
public:Person() {m_A = 0;m_B = 0;}//this指針的本質是一個指針常量,指針的指向不可修改//如果想讓指針指向的值也不可以修改,需要聲明常函數void ShowPerson() const {//const Type* const pointer;//this = NULL; //不能修改指針的指向 Person* const this;//this->mA = 100; //但是this指針指向的對象的數據是可以修改的//const修飾成員函數,表示指針指向的內存空間的數據不能修改,除了mutable修飾的變量this->m_B = 100;}void MyFunc() const {//mA = 10000;}public:int m_A;mutable int m_B; //可修改 可變的
};//const修飾對象 常對象
void test01() {const Person person; //常量對象 cout << person.m_A << endl;//person.mA = 100; //常對象不能修改成員變量的值,但是可以訪問person.m_B = 100; //但是常對象可以修改mutable修飾成員變量//常對象訪問成員函數person.MyFunc(); //常對象不能調用const的函數}int main() {test01();system("pause");return 0;
}
友元
全局函數做友元
class Building
{//告訴編譯器 goodGay全局函數 是 Building類的好朋友,可以訪問類中的私有內容friend void goodGay(Building * building);public:Building(){this->m_SittingRoom = "客廳";this->m_BedRoom = "臥室";}public:string m_SittingRoom; //客廳private:string m_BedRoom; //臥室
};void goodGay(Building * building)
{cout << "好基友正在訪問: " << building->m_SittingRoom << endl;cout << "好基友正在訪問: " << building->m_BedRoom << endl;
}void test01()
{Building b;goodGay(&b);
}int main(){test01();system("pause");return 0;
}
類做友元
class Building;
class goodGay
{
public:goodGay();void visit();private:Building *building;
};class Building
{//告訴編譯器 goodGay類是Building類的好朋友,可以訪問到Building類中私有內容friend class goodGay;public:Building();public:string m_SittingRoom; //客廳
private:string m_BedRoom;//臥室
};Building::Building()
{this->m_SittingRoom = "客廳";this->m_BedRoom = "臥室";
}goodGay::goodGay()
{building = new Building;
}void goodGay::visit()
{cout << "好基友正在訪問" << building->m_SittingRoom << endl;cout << "好基友正在訪問" << building->m_BedRoom << endl;
}void test01()
{goodGay gg;gg.visit();}int main(){test01();system("pause");return 0;
}
成員函數做友元
class Building;
class goodGay
{
public:goodGay();void visit(); //只讓visit函數作為Building的好朋友,可以發訪問Building中私有內容void visit2(); private:Building *building;
};class Building
{//告訴編譯器 goodGay類中的visit成員函數 是Building好朋友,可以訪問私有內容friend void goodGay::visit();public:Building();public:string m_SittingRoom; //客廳
private:string m_BedRoom;//臥室
};Building::Building()
{this->m_SittingRoom = "客廳";this->m_BedRoom = "臥室";
}goodGay::goodGay()
{building = new Building;
}void goodGay::visit()
{cout << "好基友正在訪問" << building->m_SittingRoom << endl;cout << "好基友正在訪問" << building->m_BedRoom << endl;
}void goodGay::visit2()
{cout << "好基友正在訪問" << building->m_SittingRoom << endl;//cout << "好基友正在訪問" << building->m_BedRoom << endl;
}void test01()
{goodGay gg;gg.visit();}int main(){test01();system("pause");return 0;
}