華夏名網(wǎng)修改網(wǎng)站信息網(wǎng)絡(luò)推廣員的前景
初始C++
注釋
變量
常量
關(guān)鍵字
標(biāo)識(shí)符命名規(guī)則
數(shù)據(jù)類(lèi)型
C++規(guī)定在創(chuàng)建一個(gè)變量或者常量時(shí),必須要指定出相應(yīng)的數(shù)據(jù)類(lèi)型,否則無(wú)法給變量分配內(nèi)存
整型
sizeof關(guān)鍵字
浮點(diǎn)型(實(shí)型)
有效位數(shù)保留七位,帶小數(shù)點(diǎn)。
這個(gè)是保留有效數(shù)字位數(shù),不包括小數(shù)點(diǎn)。
字符型
轉(zhuǎn)義字符
字符串型
布爾類(lèi)型 bool
數(shù)據(jù)的輸入
運(yùn)算符
算術(shù)運(yùn)算符
賦值運(yùn)算符
比較運(yùn)算符
邏輯運(yùn)算符
程序流程結(jié)構(gòu)
選擇結(jié)構(gòu)
if語(yǔ)句
int main() {int score = 0;cout << "請(qǐng)輸入考試分?jǐn)?shù):" << endl;cin >> score;if (score > 600){cout << "我考上了一本大學(xué)" << endl;if (score > 700){cout << "我考上了北大" << endl;}else if (score > 650){cout << "我考上了清華" << endl;}else{cout << "我考上了人大" << endl;}}else if (score > 500){cout << "我考上了二本大學(xué)" << endl;}else if (score > 400){cout << "我考上了三本大學(xué)" << endl;}else{cout << "我未考上本科" << endl;}system("pause");return 0;
}
三目運(yùn)算符
switch語(yǔ)句
循環(huán)結(jié)構(gòu)
while循環(huán)語(yǔ)句
do...while循環(huán)語(yǔ)句
for循環(huán)語(yǔ)句
嵌套循環(huán)
跳轉(zhuǎn)語(yǔ)句
break語(yǔ)句
continue語(yǔ)句
goto語(yǔ)句
數(shù)組
一維數(shù)組
冒泡排序
二維數(shù)組
函數(shù)
函數(shù)的定義
函數(shù)的調(diào)用
值傳遞
函數(shù)的常見(jiàn)樣式
函數(shù)的聲明
函數(shù)的分文件編寫(xiě)
指針
指針的定義和使用
每次p的地址是不一樣的。
指針?biāo)純?nèi)存空間
空指針和野指針
const 修飾指針
指針和數(shù)組
指針和函數(shù)
指針 數(shù)組 函數(shù)
//冒泡排序函數(shù)
void bubbleSort(int * arr, int len) //int * arr 也可以寫(xiě)為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;}}}
}//打印數(shù)組函數(shù)
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;
}
結(jié)構(gòu)體
結(jié)構(gòu)體的定義和使用
//結(jié)構(gòu)體定義
struct student
{//成員列表string name; //姓名int age; //年齡int score; //分?jǐn)?shù)
}stu3; //結(jié)構(gòu)體變量創(chuàng)建方式3 int main() {//結(jié)構(gòu)體變量創(chuàng)建方式1struct student stu1; //struct 關(guān)鍵字可以省略stu1.name = "張三";stu1.age = 18;stu1.score = 100;cout << "姓名:" << stu1.name << " 年齡:" << stu1.age << " 分?jǐn)?shù):" << stu1.score << endl;//結(jié)構(gòu)體變量創(chuàng)建方式2struct student stu2 = { "李四",19,60 };cout << "姓名:" << stu2.name << " 年齡:" << stu2.age << " 分?jǐn)?shù):" << stu2.score << endl;stu3.name = "王五";stu3.age = 18;stu3.score = 80;cout << "姓名:" << stu3.name << " 年齡:" << stu3.age << " 分?jǐn)?shù):" << stu3.score << endl;system("pause");return 0;
}
結(jié)構(gòu)體數(shù)組
結(jié)構(gòu)體指針
結(jié)構(gòu)體嵌套結(jié)構(gòu)體
//學(xué)生結(jié)構(gòu)體定義
struct student
{//成員列表string name; //姓名int age; //年齡int score; //分?jǐn)?shù)
};//教師結(jié)構(gòu)體定義
struct teacher
{//成員列表int id; //職工編號(hào)string name; //教師姓名int age; //教師年齡struct student stu; //子結(jié)構(gòu)體 學(xué)生
};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 << "教師 職工編號(hào): " << t1.id << " 姓名: " << t1.name << " 年齡: " << t1.age << endl;cout << "輔導(dǎo)學(xué)員 姓名: " << t1.stu.name << " 年齡:" << t1.stu.age << " 考試分?jǐn)?shù): " << t1.stu.score << endl;system("pause");return 0;
}
結(jié)構(gòu)體做函數(shù)參數(shù)
//學(xué)生結(jié)構(gòu)體定義
struct student
{//成員列表string name; //姓名int age; //年齡int score; //分?jǐn)?shù)
};//值傳遞
void printStudent(student stu )
{stu.age = 28;cout << "子函數(shù)中 姓名:" << stu.name << " 年齡: " << stu.age << " 分?jǐn)?shù):" << stu.score << endl;
}//地址傳遞
void printStudent2(student *stu)
{stu->age = 28;cout << "子函數(shù)中 姓名:" << stu->name << " 年齡: " << stu->age << " 分?jǐn)?shù):" << stu->score << endl;
}int main() {student stu = { "張三",18,100};//值傳遞printStudent(stu);cout << "主函數(shù)中 姓名:" << stu.name << " 年齡: " << stu.age << " 分?jǐn)?shù):" << stu.score << endl;cout << endl;//地址傳遞printStudent2(&stu);cout << "主函數(shù)中 姓名:" << stu.name << " 年齡: " << stu.age << " 分?jǐn)?shù):" << stu.score << endl;system("pause");return 0;
}
結(jié)構(gòu)體中const使用場(chǎng)景
內(nèi)存分區(qū)模型
程序運(yùn)行前
程序運(yùn)行后
new操作符
下面實(shí)例函數(shù)中,new 返回的是該數(shù)據(jù)類(lèi)型的指針。所以用 int * 來(lái)接收。
引用
引用的基本使用
引用的注意事項(xiàng)
引用做函數(shù)參數(shù)
//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;
}
引用做函數(shù)的返回值
//返回局部變量引用
int& test01() {int a = 10; //局部變量return a;
}//返回靜態(tài)變量引用
int& test02() {static int a = 20;return a;
}int main() {//不能返回局部變量的引用int& ref = test01();cout << "ref = " << ref << endl;cout << "ref = " << ref << endl;//如果函數(shù)做左值,那么必須返回引用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;
}
引用的本質(zhì)
常量引用
函數(shù)提高
函數(shù)默認(rèn)參數(shù)
如果我們自己傳入了數(shù)據(jù),就有自己的數(shù)據(jù),如果沒(méi)有,就用默認(rèn)值。
函數(shù)如果有聲明默認(rèn)值,那么函數(shù)的實(shí)現(xiàn)就不能有,聲明和實(shí)現(xiàn)只能有一個(gè)默認(rèn)參數(shù)。例如 1、2
函數(shù)占位參數(shù)
函數(shù)重載
函數(shù)重載碰到默認(rèn)參數(shù),會(huì)出現(xiàn)二義性,報(bào)錯(cuò),盡量避免這種情況。
//函數(shù)重載需要函數(shù)都在同一個(gè)作用域下
void func()
{cout << "func 的調(diào)用!" << endl;
}
void func(int a)
{cout << "func (int a) 的調(diào)用!" << endl;
}
void func(double a)
{cout << "func (double a)的調(diào)用!" << endl;
}
void func(int a ,double b)
{cout << "func (int a ,double b) 的調(diào)用!" << endl;
}
void func(double a ,int b)
{cout << "func (double a ,int b)的調(diào)用!" << endl;
}//函數(shù)返回值不可以作為函數(shù)重載條件
//int func(double a, int b)
//{
// cout << "func (double a ,int b)的調(diào)用!" << endl;
//}int main() {func();func(10);func(3.14);func(10,3.14);func(3.14 , 10);system("pause");return 0;
}
函數(shù)重載碰到默認(rèn)參數(shù),會(huì)出現(xiàn)二義性,報(bào)錯(cuò),盡量避免這種情況。
//函數(shù)重載注意事項(xiàng)
//1、引用作為重載條件void func(int &a)
{cout << "func (int &a) 調(diào)用 " << endl;
}void func(const int &a)
{cout << "func (const int &a) 調(diào)用 " << endl;
}//2、函數(shù)重載碰到函數(shù)默認(rèn)參數(shù)void func2(int a, int b = 10)
{cout << "func2(int a, int b = 10) 調(diào)用" << endl;
}void func2(int a)
{cout << "func2(int a) 調(diào)用" << endl;
}int main() {int a = 10;func(a); //調(diào)用無(wú)constfunc(10);//調(diào)用有const//func2(10); //碰到默認(rèn)參數(shù)產(chǎn)生歧義,需要避免system("pause");return 0;
}
類(lèi)和對(duì)象
封裝
//圓周率
const double PI = 3.14;//1、封裝的意義
//將屬性和行為作為一個(gè)整體,用來(lái)表現(xiàn)生活中的事物//封裝一個(gè)圓類(lèi),求圓的周長(zhǎng)
//class代表設(shè)計(jì)一個(gè)類(lèi),后面跟著的是類(lèi)名
class Circle
{
public: //訪問(wèn)權(quán)限 公共的權(quán)限//屬性int m_r;//半徑//行為//獲取到圓的周長(zhǎng)double calculateZC(){//2 * pi * r//獲取圓的周長(zhǎng)return 2 * PI * m_r;}
};int main() {//通過(guò)圓類(lèi),創(chuàng)建圓的對(duì)象// c1就是一個(gè)具體的圓Circle c1;c1.m_r = 10; //給圓對(duì)象的半徑 進(jìn)行賦值操作//2 * pi * 10 = = 62.8cout << "圓的周長(zhǎng)為: " << c1.calculateZC() << endl;system("pause");return 0;
}
//學(xué)生類(lèi)
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;
}
//三種權(quán)限
//公共權(quán)限 public 類(lèi)內(nèi)可以訪問(wèn) 類(lèi)外可以訪問(wèn)
//保護(hù)權(quán)限 protected 類(lèi)內(nèi)可以訪問(wèn) 類(lèi)外不可以訪問(wèn)
//私有權(quán)限 private 類(lèi)內(nèi)可以訪問(wèn) 類(lèi)外不可以訪問(wèn)class Person
{//姓名 公共權(quán)限
public:string m_Name;//汽車(chē) 保護(hù)權(quán)限
protected:string m_Car;//銀行卡密碼 私有權(quán)限
private:int m_Password;public:void func(){m_Name = "張三";m_Car = "拖拉機(jī)";m_Password = 123456;}
};int main() {Person p;p.m_Name = "李四";//p.m_Car = "奔馳"; //保護(hù)權(quán)限類(lèi)外訪問(wèn)不到//p.m_Password = 123; //私有權(quán)限類(lèi)外訪問(wèn)不到system("pause");return 0;
}
struct和class區(qū)別
class C1
{int m_A; //默認(rèn)是私有權(quán)限
};struct C2
{int m_A; //默認(rèn)是公共權(quán)限
};int main() {C1 c1;c1.m_A = 10; //錯(cuò)誤,訪問(wèn)權(quán)限是私有C2 c2;c2.m_A = 10; //正確,訪問(wèn)權(quán)限是公共system("pause");return 0;
}
成員屬性設(shè)置私有
class Person {
public://姓名設(shè)置可讀可寫(xiě)void setName(string name) {m_Name = name;}string getName(){return m_Name;}//獲取年齡 int getAge() {return m_Age;}//設(shè)置年齡void setAge(int age) {if (age < 0 || age > 150) {cout << "你個(gè)老妖精!" << endl;return;}m_Age = age;}//情人設(shè)置為只寫(xiě)void setLover(string lover) {m_Lover = lover;}private:string m_Name; //可讀可寫(xiě) 姓名int m_Age; //只讀 年齡string m_Lover; //只寫(xiě) 情人
};int main() {Person p;//姓名設(shè)置p.setName("張三");cout << "姓名: " << p.getName() << endl;//年齡設(shè)置p.setAge(50);cout << "年齡: " << p.getAge() << endl;//情人設(shè)置p.setLover("蒼井");//cout << "情人: " << p.m_Lover << endl; //只寫(xiě)屬性,不可以讀取system("pause");return 0;
}
對(duì)象的初始化和清理
構(gòu)造函數(shù)和析構(gòu)函數(shù)
class Person
{
public://構(gòu)造函數(shù)Person(){cout << "Person的構(gòu)造函數(shù)調(diào)用" << endl;}//析構(gòu)函數(shù)~Person(){cout << "Person的析構(gòu)函數(shù)調(diào)用" << endl;}};void test01()
{Person p;
}int main() {test01();system("pause");return 0;
}
構(gòu)造函數(shù)的分類(lèi)及調(diào)用
//1、構(gòu)造函數(shù)分類(lèi)
// 按照參數(shù)分類(lèi)分為 有參和無(wú)參構(gòu)造 無(wú)參又稱(chēng)為默認(rèn)構(gòu)造函數(shù)
// 按照類(lèi)型分類(lèi)分為 普通構(gòu)造和拷貝構(gòu)造class Person {
public://無(wú)參(默認(rèn))構(gòu)造函數(shù)Person() {cout << "無(wú)參構(gòu)造函數(shù)!" << endl;}//有參構(gòu)造函數(shù)Person(int a) {age = a;cout << "有參構(gòu)造函數(shù)!" << endl;}//拷貝構(gòu)造函數(shù)Person(const Person& p) {age = p.age;cout << "拷貝構(gòu)造函數(shù)!" << endl;}//析構(gòu)函數(shù)~Person() {cout << "析構(gòu)函數(shù)!" << endl;}
public:int age;
};//2、構(gòu)造函數(shù)的調(diào)用
//調(diào)用無(wú)參構(gòu)造函數(shù)
void test01() {Person p; //調(diào)用無(wú)參構(gòu)造函數(shù)
}//調(diào)用有參的構(gòu)造函數(shù)
void test02() {//2.1 括號(hào)法,常用Person p1(10);//注意1:調(diào)用無(wú)參構(gòu)造函數(shù)不能加括號(hào),如果加了編譯器認(rèn)為這是一個(gè)函數(shù)聲明//Person p2();//2.2 顯式法Person p2 = Person(10); Person p3 = Person(p2);//Person(10)單獨(dú)寫(xiě)就是匿名對(duì)象 當(dāng)前行結(jié)束之后,馬上析構(gòu)//2.3 隱式轉(zhuǎn)換法Person p4 = 10; // Person p4 = Person(10); Person p5 = p4; // Person p5 = Person(p4); //注意2:不能利用 拷貝構(gòu)造函數(shù) 初始化匿名對(duì)象 編譯器認(rèn)為是對(duì)象聲明//Person p5(p4);
}int main() {test01();//test02();system("pause");return 0;
}
拷貝構(gòu)造函數(shù)調(diào)用時(shí)機(jī)
class Person {
public:Person() {cout << "無(wú)參構(gòu)造函數(shù)!" << endl;mAge = 0;}Person(int age) {cout << "有參構(gòu)造函數(shù)!" << endl;mAge = age;}Person(const Person& p) {cout << "拷貝構(gòu)造函數(shù)!" << endl;mAge = p.mAge;}//析構(gòu)函數(shù)在釋放內(nèi)存之前調(diào)用~Person() {cout << "析構(gòu)函數(shù)!" << endl;}
public:int mAge;
};//1. 使用一個(gè)已經(jīng)創(chuàng)建完畢的對(duì)象來(lái)初始化一個(gè)新對(duì)象
void test01() {Person man(100); //p對(duì)象已經(jīng)創(chuàng)建完畢Person newman(man); //調(diào)用拷貝構(gòu)造函數(shù)Person newman2 = man; //拷貝構(gòu)造//Person newman3;//newman3 = man; //不是調(diào)用拷貝構(gòu)造函數(shù),賦值操作
}//2. 值傳遞的方式給函數(shù)參數(shù)傳值
//相當(dāng)于Person p1 = p;
void doWork(Person p1) {}
void test02() {Person p; //無(wú)參構(gòu)造函數(shù)doWork(p);
}//3. 以值方式返回局部對(duì)象
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;
}
構(gòu)造函數(shù)調(diào)用規(guī)則
class Person {
public://無(wú)參(默認(rèn))構(gòu)造函數(shù)Person() {cout << "無(wú)參構(gòu)造函數(shù)!" << endl;}//有參構(gòu)造函數(shù)Person(int a) {age = a;cout << "有參構(gòu)造函數(shù)!" << endl;}//拷貝構(gòu)造函數(shù)Person(const Person& p) {age = p.age;cout << "拷貝構(gòu)造函數(shù)!" << endl;}//析構(gòu)函數(shù)~Person() {cout << "析構(gòu)函數(shù)!" << endl;}
public:int age;
};void test01()
{Person p1(18);//如果不寫(xiě)拷貝構(gòu)造,編譯器會(huì)自動(dòng)添加拷貝構(gòu)造,并且做淺拷貝操作Person p2(p1);cout << "p2的年齡為: " << p2.age << endl;
}void test02()
{//如果用戶提供有參構(gòu)造,編譯器不會(huì)提供默認(rèn)構(gòu)造,會(huì)提供拷貝構(gòu)造Person p1; //此時(shí)如果用戶自己沒(méi)有提供默認(rèn)構(gòu)造,會(huì)出錯(cuò)Person p2(10); //用戶提供的有參Person p3(p2); //此時(shí)如果用戶沒(méi)有提供拷貝構(gòu)造,編譯器會(huì)提供//如果用戶提供拷貝構(gòu)造,編譯器不會(huì)提供其他構(gòu)造函數(shù)Person p4; //此時(shí)如果用戶自己沒(méi)有提供默認(rèn)構(gòu)造,會(huì)出錯(cuò)Person p5(10); //此時(shí)如果用戶自己沒(méi)有提供有參,會(huì)出錯(cuò)Person p6(p5); //用戶自己提供拷貝構(gòu)造
}int main() {test01();system("pause");return 0;
}
深拷貝與淺拷貝
class Person {
public://無(wú)參(默認(rèn))構(gòu)造函數(shù)Person() {cout << "無(wú)參構(gòu)造函數(shù)!" << endl;}//有參構(gòu)造函數(shù)Person(int age ,int height) {cout << "有參構(gòu)造函數(shù)!" << endl;m_age = age;m_height = new int(height);}//拷貝構(gòu)造函數(shù) Person(const Person& p) {cout << "拷貝構(gòu)造函數(shù)!" << endl;//如果不利用深拷貝在堆區(qū)創(chuàng)建新內(nèi)存,會(huì)導(dǎo)致淺拷貝帶來(lái)的重復(fù)釋放堆區(qū)問(wèn)題m_age = p.m_age;m_height = new int(*p.m_height);}//析構(gòu)函數(shù)~Person() {cout << "析構(gòu)函數(shù)!" << 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:傳統(tǒng)方式初始化//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;
}
類(lèi)對(duì)象作為類(lèi)成員
class Phone
{
public:Phone(string name){m_PhoneName = name;cout << "Phone構(gòu)造" << endl;}~Phone(){cout << "Phone析構(gòu)" << endl;}string m_PhoneName;};class Person
{
public://初始化列表可以告訴編譯器調(diào)用哪一個(gè)構(gòu)造函數(shù)Person(string name, string pName) :m_Name(name), m_Phone(pName){cout << "Person構(gòu)造" << endl;}~Person(){cout << "Person析構(gòu)" << endl;}void playGame(){cout << m_Name << " 使用" << m_Phone.m_PhoneName << " 牌手機(jī)! " << endl;}string m_Name;Phone m_Phone;};
void test01()
{//當(dāng)類(lèi)中成員是其他類(lèi)對(duì)象時(shí),我們稱(chēng)該成員為 對(duì)象成員//構(gòu)造的順序是 :先調(diào)用對(duì)象成員的構(gòu)造,再調(diào)用本類(lèi)構(gòu)造//析構(gòu)順序與構(gòu)造相反Person p("張三" , "蘋(píng)果X");p.playGame();}int main() {test01();system("pause");return 0;
}
靜態(tài)成員
class Person
{public:static int m_A; //靜態(tài)成員變量//靜態(tài)成員變量特點(diǎn)://1 在編譯階段分配內(nèi)存//2 類(lèi)內(nèi)聲明,類(lèi)外初始化//3 所有對(duì)象共享同一份數(shù)據(jù)private:static int m_B; //靜態(tài)成員變量也是有訪問(wèn)權(quán)限的
};
int Person::m_A = 10;
int Person::m_B = 10;void test01()
{//靜態(tài)成員變量?jī)煞N訪問(wèn)方式//1、通過(guò)對(duì)象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; //共享同一份數(shù)據(jù)cout << "p2.m_A = " << p2.m_A << endl;//2、通過(guò)類(lèi)名cout << "m_A = " << Person::m_A << endl;//cout << "m_B = " << Person::m_B << endl; //私有權(quán)限訪問(wèn)不到
}int main() {test01();system("pause");return 0;
}
class Person
{public://靜態(tài)成員函數(shù)特點(diǎn)://1 程序共享一個(gè)函數(shù)//2 靜態(tài)成員函數(shù)只能訪問(wèn)靜態(tài)成員變量static void func(){cout << "func調(diào)用" << endl;m_A = 100;//m_B = 100; //錯(cuò)誤,不可以訪問(wèn)非靜態(tài)成員變量}static int m_A; //靜態(tài)成員變量int m_B; //
private://靜態(tài)成員函數(shù)也是有訪問(wèn)權(quán)限的static void func2(){cout << "func2調(diào)用" << endl;}
};
int Person::m_A = 10;void test01()
{//靜態(tài)成員變量?jī)煞N訪問(wèn)方式//1、通過(guò)對(duì)象Person p1;p1.func();//2、通過(guò)類(lèi)名Person::func();//Person::func2(); //私有權(quán)限訪問(wèn)不到
}int main() {test01();system("pause");return 0;
}
C++對(duì)象模型和this指針
成員變量和成員函數(shù)分開(kāi)存儲(chǔ)
C++編譯器會(huì)給每一個(gè)空對(duì)象也分配一個(gè)字節(jié)空間,是為了區(qū)分空對(duì)象占內(nèi)存的位置。
每個(gè)空對(duì)象都應(yīng)該有一個(gè)獨(dú)一無(wú)二的內(nèi)存地址。
this指針概念
class Person
{
public:Person(int age){//1、當(dāng)形參和成員變量同名時(shí),可用this指針來(lái)區(qū)分this->age = age;}Person& PersonAddPerson(Person &p){this->age += p.age;//返回對(duì)象本身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;
}
空指針訪問(wèn)成員函數(shù)
//空指針訪問(wèn)成員函數(shù)
class Person {
public:void ShowClassName() {cout << "我是Person類(lèi)!" << endl;}void ShowPerson() {if (this == NULL) {return;}cout << mAge << endl;}public:int mAge;
};void test01()
{Person * p = NULL;p->ShowClassName(); //空指針,可以調(diào)用成員函數(shù)p->ShowPerson(); //但是如果成員函數(shù)中用到了this指針,就不可以了
}int main() {test01();system("pause");return 0;
}
const修飾成員函數(shù)
class Person {
public:Person() {m_A = 0;m_B = 0;}//this指針的本質(zhì)是一個(gè)指針常量,指針的指向不可修改//如果想讓指針指向的值也不可以修改,需要聲明常函數(shù)void ShowPerson() const {//const Type* const pointer;//this = NULL; //不能修改指針的指向 Person* const this;//this->mA = 100; //但是this指針指向的對(duì)象的數(shù)據(jù)是可以修改的//const修飾成員函數(shù),表示指針指向的內(nèi)存空間的數(shù)據(jù)不能修改,除了mutable修飾的變量this->m_B = 100;}void MyFunc() const {//mA = 10000;}public:int m_A;mutable int m_B; //可修改 可變的
};//const修飾對(duì)象 常對(duì)象
void test01() {const Person person; //常量對(duì)象 cout << person.m_A << endl;//person.mA = 100; //常對(duì)象不能修改成員變量的值,但是可以訪問(wèn)person.m_B = 100; //但是常對(duì)象可以修改mutable修飾成員變量//常對(duì)象訪問(wèn)成員函數(shù)person.MyFunc(); //常對(duì)象不能調(diào)用const的函數(shù)}int main() {test01();system("pause");return 0;
}
友元
全局函數(shù)做友元
class Building
{//告訴編譯器 goodGay全局函數(shù) 是 Building類(lèi)的好朋友,可以訪問(wèn)類(lèi)中的私有內(nèi)容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 << "好基友正在訪問(wèn): " << building->m_SittingRoom << endl;cout << "好基友正在訪問(wèn): " << building->m_BedRoom << endl;
}void test01()
{Building b;goodGay(&b);
}int main(){test01();system("pause");return 0;
}
類(lèi)做友元
class Building;
class goodGay
{
public:goodGay();void visit();private:Building *building;
};class Building
{//告訴編譯器 goodGay類(lèi)是Building類(lèi)的好朋友,可以訪問(wèn)到Building類(lèi)中私有內(nèi)容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 << "好基友正在訪問(wèn)" << building->m_SittingRoom << endl;cout << "好基友正在訪問(wèn)" << building->m_BedRoom << endl;
}void test01()
{goodGay gg;gg.visit();}int main(){test01();system("pause");return 0;
}
成員函數(shù)做友元
class Building;
class goodGay
{
public:goodGay();void visit(); //只讓visit函數(shù)作為Building的好朋友,可以發(fā)訪問(wèn)Building中私有內(nèi)容void visit2(); private:Building *building;
};class Building
{//告訴編譯器 goodGay類(lèi)中的visit成員函數(shù) 是Building好朋友,可以訪問(wèn)私有內(nèi)容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 << "好基友正在訪問(wèn)" << building->m_SittingRoom << endl;cout << "好基友正在訪問(wèn)" << building->m_BedRoom << endl;
}void goodGay::visit2()
{cout << "好基友正在訪問(wèn)" << building->m_SittingRoom << endl;//cout << "好基友正在訪問(wèn)" << building->m_BedRoom << endl;
}void test01()
{goodGay gg;gg.visit();}int main(){test01();system("pause");return 0;
}
運(yùn)算符重載
加號(hào)運(yùn)算符重載
class Person {
public:Person() {};Person(int a, int b){this->m_A = a;this->m_B = b;}//成員函數(shù)實(shí)現(xiàn) + 號(hào)運(yùn)算符重載Person operator+(const Person& p) {Person temp;temp.m_A = this->m_A + p.m_A;temp.m_B = this->m_B + p.m_B;return temp;}public:int m_A;int m_B;
};//全局函數(shù)實(shí)現(xiàn) + 號(hào)運(yùn)算符重載
//Person operator+(const Person& p1, const Person& p2) {
// Person temp(0, 0);
// temp.m_A = p1.m_A + p2.m_A;
// temp.m_B = p1.m_B + p2.m_B;
// return temp;
//}//運(yùn)算符重載 可以發(fā)生函數(shù)重載
Person operator+(const Person& p2, int val)
{Person temp;temp.m_A = p2.m_A + val;temp.m_B = p2.m_B + val;return temp;
}void test() {Person p1(10, 10);Person p2(20, 20);//成員函數(shù)方式Person p3 = p2 + p1; //相當(dāng)于 p2.operaor+(p1)cout << "mA:" << p3.m_A << " mB:" << p3.m_B << endl;Person p4 = p3 + 10; //相當(dāng)于 operator+(p3,10)cout << "mA:" << p4.m_A << " mB:" << p4.m_B << endl;}int main() {test();system("pause");return 0;
}
左移運(yùn)算符重載
class Person {friend ostream& operator<<(ostream& out, Person& p);public:Person(int a, int b){this->m_A = a;this->m_B = b;}//成員函數(shù) 實(shí)現(xiàn)不了 p << cout 不是我們想要的效果//void operator<<(Person& p){//}private:int m_A;int m_B;
};//全局函數(shù)實(shí)現(xiàn)左移重載
//ostream對(duì)象只能有一個(gè)
ostream& operator<<(ostream& out, Person& p) {out << "a:" << p.m_A << " b:" << p.m_B;return out;
}void test() {Person p1(10, 20);cout << p1 << "hello world" << endl; //鏈?zhǔn)骄幊?}int main() {test();system("pause");return 0;
}
遞增運(yùn)算符重載
class MyInteger {friend ostream& operator<<(ostream& out, MyInteger myint);public:MyInteger() {m_Num = 0;}//前置++MyInteger& operator++() {//先++m_Num++;//再返回return *this;}//后置++MyInteger operator++(int) {//先返回MyInteger temp = *this; //記錄當(dāng)前本身的值,然后讓本身的值加1,但是返回的是以前的值,達(dá)到先返回后++;m_Num++;return temp;}private:int m_Num;
};ostream& operator<<(ostream& out, MyInteger myint) {out << myint.m_Num;return out;
}//前置++ 先++ 再返回
void test01() {MyInteger myInt;cout << ++myInt << endl;cout << myInt << endl;
}//后置++ 先返回 再++
void test02() {MyInteger myInt;cout << myInt++ << endl;cout << myInt << endl;
}int main() {test01();//test02();system("pause");return 0;
}
賦值運(yùn)算符重載
class Person
{
public:Person(int age){//將年齡數(shù)據(jù)開(kāi)辟到堆區(qū)m_Age = new int(age);}//重載賦值運(yùn)算符 Person& operator=(Person &p){if (m_Age != NULL){delete m_Age;m_Age = NULL;}//編譯器提供的代碼是淺拷貝//m_Age = p.m_Age;//提供深拷貝 解決淺拷貝的問(wèn)題m_Age = new int(*p.m_Age);//返回自身return *this;}~Person(){if (m_Age != NULL){delete m_Age;m_Age = NULL;}}//年齡的指針int *m_Age;};void test01()
{Person p1(18);Person p2(20);Person p3(30);p3 = p2 = p1; //賦值操作cout << "p1的年齡為:" << *p1.m_Age << endl;cout << "p2的年齡為:" << *p2.m_Age << endl;cout << "p3的年齡為:" << *p3.m_Age << endl;
}int main() {test01();//int a = 10;//int b = 20;//int c = 30;//c = b = a;//cout << "a = " << a << endl;//cout << "b = " << b << endl;//cout << "c = " << c << endl;system("pause");return 0;
}
關(guān)系運(yùn)算符重載
class Person
{
public:Person(string name, int age){this->m_Name = name;this->m_Age = age;};bool operator==(Person & p){if (this->m_Name == p.m_Name && this->m_Age == p.m_Age){return true;}else{return false;}}bool operator!=(Person & p){if (this->m_Name == p.m_Name && this->m_Age == p.m_Age){return false;}else{return true;}}string m_Name;int m_Age;
};void test01()
{//int a = 0;//int b = 0;Person a("孫悟空", 18);Person b("孫悟空", 18);if (a == b){cout << "a和b相等" << endl;}else{cout << "a和b不相等" << endl;}if (a != b){cout << "a和b不相等" << endl;}else{cout << "a和b相等" << endl;}
}int main() {test01();system("pause");return 0;
}
函數(shù)調(diào)用運(yùn)算符重載
class MyPrint
{
public:void operator()(string text){cout << text << endl;}};
void test01()
{//重載的()操作符 也稱(chēng)為仿函數(shù)MyPrint myFunc;myFunc("hello world");
}class MyAdd
{
public:int operator()(int v1, int v2){return v1 + v2;}
};void test02()
{MyAdd add;int ret = add(10, 10);cout << "ret = " << ret << endl;//匿名對(duì)象調(diào)用 cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;
}int main() {test01();test02();system("pause");return 0;
}
繼承
普通實(shí)現(xiàn):
//Java頁(yè)面
class Java
{
public:void header(){cout << "首頁(yè)、公開(kāi)課、登錄、注冊(cè)...(公共頭部)" << endl;}void footer(){cout << "幫助中心、交流合作、站內(nèi)地圖...(公共底部)" << endl;}void left(){cout << "Java,Python,C++...(公共分類(lèi)列表)" << endl;}void content(){cout << "JAVA學(xué)科視頻" << endl;}
};
//Python頁(yè)面
class Python
{
public:void header(){cout << "首頁(yè)、公開(kāi)課、登錄、注冊(cè)...(公共頭部)" << endl;}void footer(){cout << "幫助中心、交流合作、站內(nèi)地圖...(公共底部)" << endl;}void left(){cout << "Java,Python,C++...(公共分類(lèi)列表)" << endl;}void content(){cout << "Python學(xué)科視頻" << endl;}
};
//C++頁(yè)面
class CPP
{
public:void header(){cout << "首頁(yè)、公開(kāi)課、登錄、注冊(cè)...(公共頭部)" << endl;}void footer(){cout << "幫助中心、交流合作、站內(nèi)地圖...(公共底部)" << endl;}void left(){cout << "Java,Python,C++...(公共分類(lèi)列表)" << endl;}void content(){cout << "C++學(xué)科視頻" << endl;}
};void test01()
{//Java頁(yè)面cout << "Java下載視頻頁(yè)面如下: " << endl;Java ja;ja.header();ja.footer();ja.left();ja.content();cout << "--------------------" << endl;//Python頁(yè)面cout << "Python下載視頻頁(yè)面如下: " << endl;Python py;py.header();py.footer();py.left();py.content();cout << "--------------------" << endl;//C++頁(yè)面cout << "C++下載視頻頁(yè)面如下: " << endl;CPP cp;cp.header();cp.footer();cp.left();cp.content();}int main() {test01();system("pause");return 0;
}
繼承實(shí)現(xiàn):
//公共頁(yè)面
class BasePage
{
public:void header(){cout << "首頁(yè)、公開(kāi)課、登錄、注冊(cè)...(公共頭部)" << endl;}void footer(){cout << "幫助中心、交流合作、站內(nèi)地圖...(公共底部)" << endl;}void left(){cout << "Java,Python,C++...(公共分類(lèi)列表)" << endl;}};//Java頁(yè)面
class Java : public BasePage
{
public:void content(){cout << "JAVA學(xué)科視頻" << endl;}
};
//Python頁(yè)面
class Python : public BasePage
{
public:void content(){cout << "Python學(xué)科視頻" << endl;}
};
//C++頁(yè)面
class CPP : public BasePage
{
public:void content(){cout << "C++學(xué)科視頻" << endl;}
};void test01()
{//Java頁(yè)面cout << "Java下載視頻頁(yè)面如下: " << endl;Java ja;ja.header();ja.footer();ja.left();ja.content();cout << "--------------------" << endl;//Python頁(yè)面cout << "Python下載視頻頁(yè)面如下: " << endl;Python py;py.header();py.footer();py.left();py.content();cout << "--------------------" << endl;//C++頁(yè)面cout << "C++下載視頻頁(yè)面如下: " << endl;CPP cp;cp.header();cp.footer();cp.left();cp.content();}int main() {test01();system("pause");return 0;
}
繼承方式
class Base1
{
public: int m_A;
protected:int m_B;
private:int m_C;
};//公共繼承
class Son1 :public Base1
{
public:void func(){m_A; //可訪問(wèn) public權(quán)限m_B; //可訪問(wèn) protected權(quán)限//m_C; //不可訪問(wèn)}
};void myClass()
{Son1 s1;s1.m_A; //其他類(lèi)只能訪問(wèn)到公共權(quán)限
}//保護(hù)繼承
class Base2
{
public:int m_A;
protected:int m_B;
private:int m_C;
};
class Son2:protected Base2
{
public:void func(){m_A; //可訪問(wèn) protected權(quán)限m_B; //可訪問(wèn) protected權(quán)限//m_C; //不可訪問(wèn)}
};
void myClass2()
{Son2 s;//s.m_A; //不可訪問(wèn)
}//私有繼承
class Base3
{
public:int m_A;
protected:int m_B;
private:int m_C;
};
class Son3:private Base3
{
public:void func(){m_A; //可訪問(wèn) private權(quán)限m_B; //可訪問(wèn) private權(quán)限//m_C; //不可訪問(wèn)}
};
class GrandSon3 :public Son3
{
public:void func(){//Son3是私有繼承,所以繼承Son3的屬性在GrandSon3中都無(wú)法訪問(wèn)到//m_A;//m_B;//m_C;}
};
繼承中的對(duì)象模型
class Base
{
public:int m_A;
protected:int m_B;
private:int m_C; //私有成員只是被隱藏了,但是還是會(huì)繼承下去
};//公共繼承
class Son :public Base
{
public:int m_D;
};void test01()
{cout << "sizeof Son = " << sizeof(Son) << endl;
}int main() {test01();system("pause");return 0;
}
繼承中的構(gòu)造和析造順序
class Base
{
public:Base(){cout << "Base構(gòu)造函數(shù)!" << endl;}~Base(){cout << "Base析構(gòu)函數(shù)!" << endl;}
};class Son : public Base
{
public:Son(){cout << "Son構(gòu)造函數(shù)!" << endl;}~Son(){cout << "Son析構(gòu)函數(shù)!" << endl;}};void test01()
{//繼承中 先調(diào)用父類(lèi)構(gòu)造函數(shù),再調(diào)用子類(lèi)構(gòu)造函數(shù),析構(gòu)順序與構(gòu)造相反Son s;
}int main() {test01();system("pause");return 0;
}
繼承同名成員處理方式
class Base {
public:Base(){m_A = 100;}void func(){cout << "Base - func()調(diào)用" << endl;}void func(int a){cout << "Base - func(int a)調(diào)用" << endl;}public:int m_A;
};class Son : public Base {
public:Son(){m_A = 200;}//當(dāng)子類(lèi)與父類(lèi)擁有同名的成員函數(shù),子類(lèi)會(huì)隱藏父類(lèi)中所有版本的同名成員函數(shù)//如果想訪問(wèn)父類(lèi)中被隱藏的同名成員函數(shù),需要加父類(lèi)的作用域void func(){cout << "Son - func()調(diào)用" << endl;}
public:int m_A;
};void test01()
{Son s;cout << "Son下的m_A = " << s.m_A << endl;cout << "Base下的m_A = " << s.Base::m_A << endl;s.func();s.Base::func();s.Base::func(10);}
int main() {test01();system("pause");return EXIT_SUCCESS;
}
繼承同名靜態(tài)成員處理方式
class Base {
public:static void func(){cout << "Base - static void func()" << endl;}static void func(int a){cout << "Base - static void func(int a)" << endl;}static int m_A;
};int Base::m_A = 100;class Son : public Base {
public:static void func(){cout << "Son - static void func()" << endl;}static int m_A;
};int Son::m_A = 200;//同名成員屬性
void test01()
{//通過(guò)對(duì)象訪問(wèn)cout << "通過(guò)對(duì)象訪問(wèn): " << endl;Son s;cout << "Son 下 m_A = " << s.m_A << endl;cout << "Base 下 m_A = " << s.Base::m_A << endl;//通過(guò)類(lèi)名訪問(wèn)cout << "通過(guò)類(lèi)名訪問(wèn): " << endl;cout << "Son 下 m_A = " << Son::m_A << endl;cout << "Base 下 m_A = " << Son::Base::m_A << endl;
}//同名成員函數(shù)
void test02()
{//通過(guò)對(duì)象訪問(wèn)cout << "通過(guò)對(duì)象訪問(wèn): " << endl;Son s;s.func();s.Base::func();cout << "通過(guò)類(lèi)名訪問(wèn): " << endl;Son::func();Son::Base::func();//出現(xiàn)同名,子類(lèi)會(huì)隱藏掉父類(lèi)中所有同名成員函數(shù),需要加作作用域訪問(wèn)Son::Base::func(100);
}
int main() {//test01();test02();system("pause");return 0;
}
多繼承語(yǔ)法
class Base1 {
public:Base1(){m_A = 100;}
public:int m_A;
};class Base2 {
public:Base2(){m_A = 200; //開(kāi)始是m_B 不會(huì)出問(wèn)題,但是改為mA就會(huì)出現(xiàn)不明確}
public:int m_A;
};//語(yǔ)法:class 子類(lèi):繼承方式 父類(lèi)1 ,繼承方式 父類(lèi)2
class Son : public Base2, public Base1
{
public:Son(){m_C = 300;m_D = 400;}
public:int m_C;int m_D;
};//多繼承容易產(chǎn)生成員同名的情況
//通過(guò)使用類(lèi)名作用域可以區(qū)分調(diào)用哪一個(gè)基類(lèi)的成員
void test01()
{Son s;cout << "sizeof Son = " << sizeof(s) << endl;cout << s.Base1::m_A << endl;cout << s.Base2::m_A << endl;
}int main() {test01();system("pause");return 0;
}
菱形繼承
當(dāng)菱形繼承時(shí),兩個(gè)父類(lèi)擁有相同數(shù)據(jù),需要加以作用域區(qū)分。
class Animal
{
public:int m_Age;
};//繼承前加virtual關(guān)鍵字后,變?yōu)樘摾^承
//此時(shí)公共的父類(lèi)Animal稱(chēng)為虛基類(lèi)
class Sheep : virtual public Animal {};
class Tuo : virtual public Animal {};
class SheepTuo : public Sheep, public Tuo {};void test01()
{SheepTuo st;st.Sheep::m_Age = 100;st.Tuo::m_Age = 200;cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;cout << "st.Tuo::m_Age = " << st.Tuo::m_Age << endl;cout << "st.m_Age = " << st.m_Age << endl;
}int main() {test01();system("pause");return 0;
}
多態(tài)
class Animal
{
public://Speak函數(shù)就是虛函數(shù)//函數(shù)前面加上virtual關(guān)鍵字,變成虛函數(shù),那么編譯器在編譯的時(shí)候就不能確定函數(shù)調(diào)用了。virtual void speak(){cout << "動(dòng)物在說(shuō)話" << endl;}
};class Cat :public Animal
{
public:void speak(){cout << "小貓?jiān)谡f(shuō)話" << endl;}
};class Dog :public Animal
{
public:void speak(){cout << "小狗在說(shuō)話" << endl;}};
//我們希望傳入什么對(duì)象,那么就調(diào)用什么對(duì)象的函數(shù)
//如果函數(shù)地址在編譯階段就能確定,那么靜態(tài)聯(lián)編
//如果函數(shù)地址在運(yùn)行階段才能確定,就是動(dòng)態(tài)聯(lián)編void DoSpeak(Animal & animal)
{animal.speak();
}
//
//多態(tài)滿足條件:
//1、有繼承關(guān)系
//2、子類(lèi)重寫(xiě)父類(lèi)中的虛函數(shù)
//多態(tài)使用:
//父類(lèi)指針或引用指向子類(lèi)對(duì)象void test01()
{Cat cat;DoSpeak(cat);Dog dog;DoSpeak(dog);
}int main() {test01();system("pause");return 0;
}
純虛函數(shù)和抽象類(lèi)
class Base
{
public://純虛函數(shù)//類(lèi)中只要有一個(gè)純虛函數(shù)就稱(chēng)為抽象類(lèi)//抽象類(lèi)無(wú)法實(shí)例化對(duì)象//子類(lèi)必須重寫(xiě)父類(lèi)中的純虛函數(shù),否則也屬于抽象類(lèi)virtual void func() = 0;
};class Son :public Base
{
public:virtual void func() {cout << "func調(diào)用" << endl;};
};void test01()
{Base * base = NULL;//base = new Base; // 錯(cuò)誤,抽象類(lèi)無(wú)法實(shí)例化對(duì)象base = new Son;base->func();delete base;//記得銷(xiāo)毀
}int main() {test01();system("pause");return 0;
}
虛析構(gòu)和純虛析構(gòu)
class Animal {
public:Animal(){cout << "Animal 構(gòu)造函數(shù)調(diào)用!" << endl;}virtual void Speak() = 0;//析構(gòu)函數(shù)加上virtual關(guān)鍵字,變成虛析構(gòu)函數(shù)//virtual ~Animal()//{// cout << "Animal虛析構(gòu)函數(shù)調(diào)用!" << endl;//}virtual ~Animal() = 0;
};Animal::~Animal()
{cout << "Animal 純虛析構(gòu)函數(shù)調(diào)用!" << endl;
}//和包含普通純虛函數(shù)的類(lèi)一樣,包含了純虛析構(gòu)函數(shù)的類(lèi)也是一個(gè)抽象類(lèi)。不能夠被實(shí)例化。class Cat : public Animal {
public:Cat(string name){cout << "Cat構(gòu)造函數(shù)調(diào)用!" << endl;m_Name = new string(name);}virtual void Speak(){cout << *m_Name << "小貓?jiān)谡f(shuō)話!" << endl;}~Cat(){cout << "Cat析構(gòu)函數(shù)調(diào)用!" << endl;if (this->m_Name != NULL) {delete m_Name;m_Name = NULL;}}public:string *m_Name;
};void test01()
{Animal *animal = new Cat("Tom");animal->Speak();//通過(guò)父類(lèi)指針去釋放,會(huì)導(dǎo)致子類(lèi)對(duì)象可能清理不干凈,造成內(nèi)存泄漏//怎么解決?給基類(lèi)增加一個(gè)虛析構(gòu)函數(shù)//虛析構(gòu)函數(shù)就是用來(lái)解決通過(guò)父類(lèi)指針釋放子類(lèi)對(duì)象delete animal;
}int main() {test01();system("pause");return 0;
}
文件操作
文本文件
寫(xiě)文件
#include <fstream>void test01()
{ofstream ofs;ofs.open("test.txt", ios::out);ofs << "姓名:張三" << endl;ofs << "性別:男" << endl;ofs << "年齡:18" << endl;ofs.close();
}int main() {test01();system("pause");return 0;
}
讀文件
#include <fstream>
#include <string>
void test01()
{ifstream ifs;ifs.open("test.txt", ios::in);if (!ifs.is_open()){cout << "文件打開(kāi)失敗" << endl;return;}//第一種方式//char buf[1024] = { 0 };//while (ifs >> buf)//{// cout << buf << endl;//}//第二種//char buf[1024] = { 0 };//while (ifs.getline(buf,sizeof(buf)))//{// cout << buf << endl;//}//第三種//string buf;//while (getline(ifs, buf))//{// cout << buf << endl;//}char c;while ((c = ifs.get()) != EOF){cout << c;}ifs.close();}int main() {test01();system("pause");return 0;
}
二進(jìn)制文件
寫(xiě)文件
#include <fstream>
#include <string>class Person
{
public:char m_Name[64];int m_Age;
};//二進(jìn)制文件 寫(xiě)文件
void test01()
{//1、包含頭文件//2、創(chuàng)建輸出流對(duì)象ofstream ofs("person.txt", ios::out | ios::binary);//3、打開(kāi)文件//ofs.open("person.txt", ios::out | ios::binary);Person p = {"張三" , 18};//4、寫(xiě)文件ofs.write((const char *)&p, sizeof(p));//5、關(guān)閉文件ofs.close();
}int main() {test01();system("pause");return 0;
}
讀文件
#include <fstream>
#include <string>class Person
{
public:char m_Name[64];int m_Age;
};void test01()
{ifstream ifs("person.txt", ios::in | ios::binary);if (!ifs.is_open()){cout << "文件打開(kāi)失敗" << endl;}Person p;ifs.read((char *)&p, sizeof(p));cout << "姓名: " << p.m_Name << " 年齡: " << p.m_Age << endl;
}int main() {test01();system("pause");return 0;
}
模板
函數(shù)模板
函數(shù)模板
//交換整型函數(shù)
void swapInt(int& a, int& b) {int temp = a;a = b;b = temp;
}//交換浮點(diǎn)型函數(shù)
void swapDouble(double& a, double& b) {double temp = a;a = b;b = temp;
}//利用模板提供通用的交換函數(shù)
template<typename T>
void mySwap(T& a, T& b)
{T temp = a;a = b;b = temp;
}void test01()
{int a = 10;int b = 20;//swapInt(a, b);//利用模板實(shí)現(xiàn)交換//1、自動(dòng)類(lèi)型推導(dǎo)mySwap(a, b);//2、顯示指定類(lèi)型mySwap<int>(a, b);cout << "a = " << a << endl;cout << "b = " << b << endl;}int main() {test01();system("pause");return 0;
}
函數(shù)模板注意事項(xiàng)
//利用模板提供通用的交換函數(shù)
template<class T>
void mySwap(T& a, T& b)
{T temp = a;a = b;b = temp;
}// 1、自動(dòng)類(lèi)型推導(dǎo),必須推導(dǎo)出一致的數(shù)據(jù)類(lèi)型T,才可以使用
void test01()
{int a = 10;int b = 20;char c = 'c';mySwap(a, b); // 正確,可以推導(dǎo)出一致的T//mySwap(a, c); // 錯(cuò)誤,推導(dǎo)不出一致的T類(lèi)型
}// 2、模板必須要確定出T的數(shù)據(jù)類(lèi)型,才可以使用
template<class T>
void func()
{cout << "func 調(diào)用" << endl;
}void test02()
{//func(); //錯(cuò)誤,模板不能獨(dú)立使用,必須確定出T的類(lèi)型func<int>(); //利用顯示指定類(lèi)型的方式,給T一個(gè)類(lèi)型,才可以使用該模板
}int main() {test01();test02();system("pause");return 0;
}
普通函數(shù)與函數(shù)模板的區(qū)別
//普通函數(shù)
int myAdd01(int a, int b)
{return a + b;
}//函數(shù)模板
template<class T>
T myAdd02(T a, T b)
{return a + b;
}//使用函數(shù)模板時(shí),如果用自動(dòng)類(lèi)型推導(dǎo),不會(huì)發(fā)生自動(dòng)類(lèi)型轉(zhuǎn)換,即隱式類(lèi)型轉(zhuǎn)換
void test01()
{int a = 10;int b = 20;char c = 'c';cout << myAdd01(a, c) << endl; //正確,將char類(lèi)型的'c'隱式轉(zhuǎn)換為int類(lèi)型 'c' 對(duì)應(yīng) ASCII碼 99//myAdd02(a, c); // 報(bào)錯(cuò),使用自動(dòng)類(lèi)型推導(dǎo)時(shí),不會(huì)發(fā)生隱式類(lèi)型轉(zhuǎn)換myAdd02<int>(a, c); //正確,如果用顯示指定類(lèi)型,可以發(fā)生隱式類(lèi)型轉(zhuǎn)換
}int main() {test01();system("pause");return 0;
}
普通函數(shù)與函數(shù)模板的調(diào)用規(guī)則
//普通函數(shù)與函數(shù)模板調(diào)用規(guī)則
void myPrint(int a, int b)
{cout << "調(diào)用的普通函數(shù)" << endl;
}template<typename T>
void myPrint(T a, T b)
{ cout << "調(diào)用的模板" << endl;
}template<typename T>
void myPrint(T a, T b, T c)
{ cout << "調(diào)用重載的模板" << endl;
}void test01()
{//1、如果函數(shù)模板和普通函數(shù)都可以實(shí)現(xiàn),優(yōu)先調(diào)用普通函數(shù)// 注意 如果告訴編譯器 普通函數(shù)是有的,但只是聲明沒(méi)有實(shí)現(xiàn),或者不在當(dāng)前文件內(nèi)實(shí)現(xiàn),就會(huì)報(bào)錯(cuò)找不到int a = 10;int b = 20;myPrint(a, b); //調(diào)用普通函數(shù)//2、可以通過(guò)空模板參數(shù)列表來(lái)強(qiáng)制調(diào)用函數(shù)模板myPrint<>(a, b); //調(diào)用函數(shù)模板//3、函數(shù)模板也可以發(fā)生重載int c = 30;myPrint(a, b, c); //調(diào)用重載的函數(shù)模板//4、 如果函數(shù)模板可以產(chǎn)生更好的匹配,優(yōu)先調(diào)用函數(shù)模板char c1 = 'a';char c2 = 'b';myPrint(c1, c2); //調(diào)用函數(shù)模板
}int main() {test01();system("pause");return 0;
}
模板的局限性
#include<iostream>
using namespace std;#include <string>class Person
{
public:Person(string name, int age){this->m_Name = name;this->m_Age = age;}string m_Name;int m_Age;
};//普通函數(shù)模板
template<class T>
bool myCompare(T& a, T& b)
{if (a == b){return true;}else{return false;}
}//具體化,顯示具體化的原型和定意思以template<>開(kāi)頭,并通過(guò)名稱(chēng)來(lái)指出類(lèi)型
//具體化優(yōu)先于常規(guī)模板
template<> bool myCompare(Person &p1, Person &p2)
{if ( p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age){return true;}else{return false;}
}void test01()
{int a = 10;int b = 20;//內(nèi)置數(shù)據(jù)類(lèi)型可以直接使用通用的函數(shù)模板bool ret = myCompare(a, b);if (ret){cout << "a == b " << endl;}else{cout << "a != b " << endl;}
}void test02()
{Person p1("Tom", 10);Person p2("Tom", 10);//自定義數(shù)據(jù)類(lèi)型,不會(huì)調(diào)用普通的函數(shù)模板//可以創(chuàng)建具體化的Person數(shù)據(jù)類(lèi)型的模板,用于特殊處理這個(gè)類(lèi)型bool ret = myCompare(p1, p2);if (ret){cout << "p1 == p2 " << endl;}else{cout << "p1 != p2 " << endl;}
}int main() {test01();test02();system("pause");return 0;
}
類(lèi)模板
#include <string>
//類(lèi)模板
template<class NameType, class AgeType>
class Person
{
public:Person(NameType name, AgeType age){this->mName = name;this->mAge = age;}void showPerson(){cout << "name: " << this->mName << " age: " << this->mAge << endl;}
public:NameType mName;AgeType mAge;
};void test01()
{// 指定NameType 為string類(lèi)型,AgeType 為 int類(lèi)型Person<string, int>P1("孫悟空", 999);P1.showPerson();
}int main() {test01();system("pause");return 0;
}
類(lèi)模板與函數(shù)模板的區(qū)別
#include <string>
//類(lèi)模板
template<class NameType, class AgeType = int>
class Person
{
public:Person(NameType name, AgeType age){this->mName = name;this->mAge = age;}void showPerson(){cout << "name: " << this->mName << " age: " << this->mAge << endl;}
public:NameType mName;AgeType mAge;
};//1、類(lèi)模板沒(méi)有自動(dòng)類(lèi)型推導(dǎo)的使用方式
void test01()
{// Person p("孫悟空", 1000); // 錯(cuò)誤 類(lèi)模板使用時(shí)候,不可以用自動(dòng)類(lèi)型推導(dǎo)Person <string ,int>p("孫悟空", 1000); //必須使用顯示指定類(lèi)型的方式,使用類(lèi)模板p.showPerson();
}//2、類(lèi)模板在模板參數(shù)列表中可以有默認(rèn)參數(shù)
void test02()
{Person <string> p("豬八戒", 999); //類(lèi)模板中的模板參數(shù)列表 可以指定默認(rèn)參數(shù)p.showPerson();
}int main() {test01();test02();system("pause");return 0;
}
類(lèi)模板中成員函數(shù)創(chuàng)建時(shí)機(jī)
class Person1
{
public:void showPerson1(){cout << "Person1 show" << endl;}
};class Person2
{
public:void showPerson2(){cout << "Person2 show" << endl;}
};template<class T>
class MyClass
{
public:T obj;//類(lèi)模板中的成員函數(shù),并不是一開(kāi)始就創(chuàng)建的,而是在模板調(diào)用時(shí)再生成void fun1() { obj.showPerson1(); }void fun2() { obj.showPerson2(); }};void test01()
{MyClass<Person1> m;m.fun1();//m.fun2();//編譯會(huì)出錯(cuò),說(shuō)明函數(shù)調(diào)用才會(huì)去創(chuàng)建成員函數(shù)
}int main() {test01();system("pause");return 0;
}
類(lèi)模板對(duì)象做函數(shù)參數(shù)
#include <string>
//類(lèi)模板
template<class NameType, class AgeType = int>
class Person
{
public:Person(NameType name, AgeType age){this->mName = name;this->mAge = age;}void showPerson(){cout << "name: " << this->mName << " age: " << this->mAge << endl;}
public:NameType mName;AgeType mAge;
};//1、指定傳入的類(lèi)型
void printPerson1(Person<string, int> &p)
{p.showPerson();
}
void test01()
{Person <string, int >p("孫悟空", 100);printPerson1(p);
}//2、參數(shù)模板化
template <class T1, class T2>
void printPerson2(Person<T1, T2>&p)
{p.showPerson();cout << "T1的類(lèi)型為: " << typeid(T1).name() << endl;cout << "T2的類(lèi)型為: " << typeid(T2).name() << endl;
}
void test02()
{Person <string, int >p("豬八戒", 90);printPerson2(p);
}//3、整個(gè)類(lèi)模板化
template<class T>
void printPerson3(T & p)
{cout << "T的類(lèi)型為: " << typeid(T).name() << endl;p.showPerson();}
void test03()
{Person <string, int >p("唐僧", 30);printPerson3(p);
}int main() {test01();test02();test03();system("pause");return 0;
}
類(lèi)模板與繼承
template<class T>
class Base
{T m;
};//class Son:public Base //錯(cuò)誤,c++編譯需要給子類(lèi)分配內(nèi)存,必須知道父類(lèi)中T的類(lèi)型才可以向下繼承
class Son :public Base<int> //必須指定一個(gè)類(lèi)型
{
};
void test01()
{Son c;
}//類(lèi)模板繼承類(lèi)模板 ,可以用T2指定父類(lèi)中的T類(lèi)型
template<class T1, class T2>
class Son2 :public Base<T2>
{
public:Son2(){cout << typeid(T1).name() << endl;cout << typeid(T2).name() << endl;}
};void test02()
{Son2<int, char> child1;
}int main() {test01();test02();system("pause");return 0;
}
類(lèi)模板成員函數(shù)類(lèi)外實(shí)現(xiàn)
#include <string>//類(lèi)模板中成員函數(shù)類(lèi)外實(shí)現(xiàn)
template<class T1, class T2>
class Person {
public://成員函數(shù)類(lèi)內(nèi)聲明Person(T1 name, T2 age);void showPerson();public:T1 m_Name;T2 m_Age;
};//構(gòu)造函數(shù) 類(lèi)外實(shí)現(xiàn)
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {this->m_Name = name;this->m_Age = age;
}//成員函數(shù) 類(lèi)外實(shí)現(xiàn)
template<class T1, class T2>
void Person<T1, T2>::showPerson() {cout << "姓名: " << this->m_Name << " 年齡:" << this->m_Age << endl;
}void test01()
{Person<string, int> p("Tom", 20);p.showPerson();
}int main() {test01();system("pause");return 0;
}
類(lèi)模板分文件編寫(xiě)

???????類(lèi)模板與友元
#include <string>//2、全局函數(shù)配合友元 類(lèi)外實(shí)現(xiàn) - 先做函數(shù)模板聲明,下方在做函數(shù)模板定義,在做友元
template<class T1, class T2> class Person;//如果聲明了函數(shù)模板,可以將實(shí)現(xiàn)寫(xiě)到后面,否則需要將實(shí)現(xiàn)體寫(xiě)到類(lèi)的前面讓編譯器提前看到
//template<class T1, class T2> void printPerson2(Person<T1, T2> & p); template<class T1, class T2>
void printPerson2(Person<T1, T2> & p)
{cout << "類(lèi)外實(shí)現(xiàn) ---- 姓名: " << p.m_Name << " 年齡:" << p.m_Age << endl;
}template<class T1, class T2>
class Person
{//1、全局函數(shù)配合友元 類(lèi)內(nèi)實(shí)現(xiàn)friend void printPerson(Person<T1, T2> & p){cout << "姓名: " << p.m_Name << " 年齡:" << p.m_Age << endl;}//全局函數(shù)配合友元 類(lèi)外實(shí)現(xiàn)friend void printPerson2<>(Person<T1, T2> & p);public:Person(T1 name, T2 age){this->m_Name = name;this->m_Age = age;}private:T1 m_Name;T2 m_Age;};//1、全局函數(shù)在類(lèi)內(nèi)實(shí)現(xiàn)
void test01()
{Person <string, int >p("Tom", 20);printPerson(p);
}//2、全局函數(shù)在類(lèi)外實(shí)現(xiàn)
void test02()
{Person <string, int >p("Jerry", 30);printPerson2(p);
}int main() {//test01();test02();system("pause");return 0;
}