1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > C++学习笔记(B站黑马程序员C++教程)

C++学习笔记(B站黑马程序员C++教程)

时间:2020-01-15 21:15:38

相关推荐

C++学习笔记(B站黑马程序员C++教程)

C++学习笔记(B站黑马程序员C++教程)

简介

视频链接/video/BV1kV411U7Ub?spm_id_from=333.999.0.0

建议用python或者浏览器视频插件把视频先下下来,万一没了呢!!!

第10-20章

目录

十一、动态对象创造

十二、静态成员函数

十三、 单例模式

十四、 初识对象和this指针

十五、 空指针访问成员函数

十六、 全局函数做友元函数

十七、动态数组

十八、运算符重载

十九、强化训练字符封装

二十、继承

十一、动态对象创造

动态对象创造//malloc和new的区别//malloc和free属于库函数new和delete属于运算符//malloc不会调用构造函数new会调用构造函数//malloc返回void*C++下需要强转new返回创建的对象指针classPerson{public:Person(){cout<<"Person构造函数构造调用"<<endl;}Person(inta){cout<<"Person有参构造函数构造调用"<<endl;}~Person(){cout<<"Person析构函数构造调用"<<endl;}private:};voidtest01(){Person*p=newPerson;deletep;}//注意事项://不要用void*去接受new出来的对象//voidtest02(){void*p=newPerson;deletep;//用不了析构无法释放delete(Person*)p;//这么可以但不提倡}//利用new开辟数组voidtest03(){//常规数组//int*pint=newint[10];//double*pD=newdouble[10];//会调用默认构造函数,堆区调用数组一定会调用默认构造函数//尽量用new新建class后,建立默认函数,否则有可能在类建立带参构造函数时,系统不自带初始默认函数Person*p_Person=newPerson[10];delete[]p_Person;//释放数组多加一个[]}voidtest04(){//栈上开辟数组,可以没有默认构造PersonpArray[10]={Person(10),Person(20),Person(30)};}

十二、静态成员函数

静态成员变量//1.静态成员变量classMyClass{public:MyClass(){}~MyClass(){}//静态成员变量,编译阶段分配了内存//必须类内声明、类外初始化//静态成员变量所有对象都共享同一份数据staticintm_a;private:staticintm_b;};intMyClass::m_a=0;voidtest(){//1.通过对象进行访问MyClassp1;cout<<p1.m_a<<endl;MyClassp2;p2.m_a=100;cout<<p2.m_a<<endl;//2.通过类名进行访问cout<<MyClass::m_a<<endl;//cout<<MyClass::m_b<<endl;//私有静态变量类外访问不到,静态变量有访问权限}静态成员函数//静态成员函数//所有对象都共享一个成员函数//注意:静态函数只能调用静态变量classPerson{public://静态成员函数//所有对象都共享一个成员函数//注意:静态函数只能调用静态变量staticvoidfunc(){m_b=20;/*m_a=10;*/cout<<"func调用"<<endl;}private:intm_a=0;staticintm_b;};intPerson::m_b=100;voidtest01(){//1.通过对象Personp1;p1.func();//2.通过类名Person::func();}

十三、单例模式

主席案例//单利全局只有一个//单例模式主席类案例classChairMan{public:staticChairMan*GetInstance()//实例{returnSingleMan;}private://将构造函数私有化,不可以创建多个对象ChairMan(){};ChairMan(constChairMan&){};//public:将主席指针私有,对外只提供制度接口,防止主席被释放staticChairMan*SingleMan;//类内声明,类外初始化};ChairMan*ChairMan::SingleMan=newChairMan;voidtest01(){/*ChairMan*c1=ChairMan::SingleMan;*//*ChairMan::SingleMan=NULL;*///不能直接操作值ChairMan*c1=ChairMan::GetInstance();/*ChairMan*c3=newChairMan(c1);*/deletec1;//可以释放操作}打印机案例//单利打印机classPrinter{public:staticPrinter*GetInstance(){returnprinter;}voidPrinterTest(stringtest){m_count++;cout<<test<<endl;}intm_count;private:Printer(){m_count=0;};Printer(constPrinter&p){};staticPrinter*printer;//编译阶段分配内存,程序没运行打印};Printer*Printer::printer=newPrinter;voidtest02(){Printer*p1=Printer::GetInstance();p1->PrinterTest("入职证明");p1->PrinterTest("身份证");Printer*p2=Printer::GetInstance();p2->PrinterTest("打印机使用次数");cout<<p2->m_count<<endl;/*cout<<Printer::m_count<<endl;*///非静态成员只能对应某个对象访问}

十四、初识对象和this指针

classPerson{};sizeof(Person)==1//空对象内存为一字节classPerson{inta;intfunc();};sizeof(Person)==4//原因成员函数存储空间分开存储#pragmapack(show)对齐模数只有非静态成员变量属于对象上,其他都是一份;this指针classPerson{inta;intfunc(this);//隐式添加,谁调用this就指向谁};//this指针//用途1:解决名称冲突//性质:隐藏在每个成员函数中//*this本体//链式编程思想classPerson{public:Person(intage)//Person*this类型{m_age=age;this->age=age;//成员变量重名用this区分}Person&PersonAddPerson(Person&p){this->age+=p.age;return*this;}intage;intm_age;private:};voidtest01(){Personp1(18);cout<<p1.age<<endl;Personp2(10);p1.PersonAddPerson(p2).PersonAddPerson(p2).PersonAddPerson(p2);//链式编程cout<<"p1.age为"<<p1.age<<endl;}

十五、空指针访问成员函数

空指针1.成员函数没有用到this指针可以调用2.成员函数有用到this指针不可以调用classPerson{public:Person(){};~Person(){};voidShowClass(){cout<<"classNameisPerson"<<endl;}voidShowAge(){if(this==NULL){//防止调用空指针,防止代码崩掉return;}m_age=0;cout<<"age="<<this->m_age<<endl;}intm_age;private:};voidtest01(){Person*p=NULL;//没有类空间成员属性可以调用p->ShowClass();//有类空间成员属性不可以调用p->ShowAge();}常函数和常对象常对象只可以修改加mutable前缀属性,和常数调用,不可以调普通成员函数和普通属性目的给*this指针加上const使指针的值也不可以改变classPerson{public:Person(){};Person(intage){this->m_age=age;};/*voidShowPerson(){*/voidShowPerson()const{//在一个类函数后边加const修饰成员函数中的this指针//Person*constthis变成constPerson*constthis/*m_age=100;*///常函数下不对m_a=100;//特殊的属性也可以改//防止m_age修改//this指针的本质Person*constthis//constPerson*constthis所有都不能修改cout<<"Personage="<<m_age<<endl;}~Person(){};intm_age;mutableintm_a;//在常函数中常对象加mutable特殊的属性也可以改};voidtest01(){Personp(10);//常对象只可以修改加mutable前缀属性,和常数调用,不可以调普通成员函数和普通属性constPersonp1(10);p1.ShowPerson();p1.m_a=10;}

十六、全局函数做友元函数

注意:friend不具有互逆行,只有定义friend才可以访问//友元函数,可以把一个全局函数,某个类中的成员函数,甚至整个类声明为友元classBuliding{friendvoidgoodfriend(Buliding*buliding);public:Buliding(){this->m_sittingrom="客厅";this->m_bedroom="卧室";};~Buliding(){};stringm_sittingrom;private:stringm_bedroom;};//好朋友全局函数,可以访问Buliding的私有属性voidgoodfriend(Buliding*buliding){cout<<"好朋友正在访问:"<<buliding->m_sittingrom<<endl;cout<<"好朋友正在访问:"<<buliding->m_bedroom<<endl;}voidtest01(){Bulidingbuliding;goodfriend(&buliding);}整个类作为友元classBuilding;//类的声明classGoodFriend{public:GoodFriend();voidvisit();Building*m_building;~GoodFriend(){};private:};classBuilding{//让goodfriend友元friendclassGoodFriend;public:Building();stringm_sittingrom;~Building(){};private:stringm_bedrom;};Building::Building(){this->m_sittingrom="客厅";this->m_bedrom="卧室";}GoodFriend::GoodFriend(){this->m_building=newBuilding;}voidGoodFriend::visit(){cout<<"好朋友正在访问"<<this->m_building->m_sittingrom<<endl;cout<<"好朋友正在访问"<<this->m_building->m_bedrom<<endl;}voidtest01(){GoodFriendff;ff.visit();}friendvoidGoodFriend::visit();某个类成员函数作为友元;

十七、动态数组

MyArry.h#pragmaonce#define_CRT_SECURE_NO_WARNINGS#include<iostream>usingnamespacestd;classMyArray{public:MyArray();//默认构造给100个容量MyArray(intcapacity);MyArray(constMyArray&arr);//尾插法voidPushBack(intval);//根据位置设置数据voidSetData(intpos,intval);//根据位置获取数据intGetData(intpos);//中括号获取数组元素int*GetArray();//获取数组大小intGetSize();~MyArray();private:intm_capacity;//数组容量intm_size;//数组大小int*pAddress;//真实在堆区开辟的数组的指针};MyArry.cpp#include"MyArray.h"//默认构造给100个容量MyArray::MyArray(){this->m_capacity=100;this->m_size=0;this->pAddress=newint[this->m_capacity];}MyArray::MyArray(intcapacity){this->m_capacity=capacity;this->m_size=0;this->pAddress=newint[this->m_capacity];}MyArray::MyArray(constMyArray&arr){this->m_capacity=arr.m_capacity;this->m_size=arr.m_size;this->pAddress=newint[arr.m_capacity];for(inti=0;i<m_size;i++){this->pAddress[i]=arr.pAddress[i];}}//尾插法voidMyArray::PushBack(intval){this->pAddress[this->m_size]=val;this->m_size++;}//根据位置设置数据voidMyArray::SetData(intpos,intval){this->pAddress[pos]=val;}//根据位置获取数据intMyArray::GetData(intpos){returnthis->pAddress[pos];}//中括号获取数组元素int*MyArray::GetArray(){returnthis->pAddress;}//获取数组大小intMyArray::GetSize(){returnthis->m_size;}MyArray::~MyArray(){if(this->pAddress!=NULL){delete[]this->pAddress;this->pAddress=NULL;}}test.cpp#define_CRT_SECURE_NO_WARNINGS#include<iostream>#include"MyArray.h"usingnamespacestd;//测试功能voidtest01(){MyArrayarr;for(inti=0;i<10;i++){arr.PushBack(i);}for(inti=0;i<arr.GetSize();i++){cout<<arr.GetData(i)<<endl;}MyArrayarr2(arr);for(inti=0;i<arr2.GetSize();i++){cout<<arr2.GetData(i)<<endl;}arr.SetData(0,1000);cout<<"arr[0]="<<arr.GetData(0)<<endl;int*arr3=arr.GetArray();arr3[0]=10;cout<<"arr3[0]="<<arr.GetData(0)<<endl;cout<<"arr3[0]="<<arr3[0]<<endl;}intmain(intargc,char*argv[]){test01();system("pause");returnEXIT_SUCCESS;}

十八、运算符重载

加号运算符重载注意:加号重载运算符可以重载函数//Personp3=operator+(p1,p2);//全局函数本质//Personp3=p1.operator+(p2);//全局函数本质classPerson{public:Person(){};//注意大括号;Person(inta,intb):m_a(a),m_b(b){};利用函数实现加号运算符重载//Personoperator+(Person&p)//{//Persontemp;//temp.m_a=this->m_a+p.m_a;//temp.m_b=this->m_b+p.m_b;//returntemp;//}~Person(){};intm_a;intm_b;};//利用全局函数加号运算符重载Personoperator+(Person&p1,Person&p2){Persontemp;temp.m_a=p1.m_a+p2.m_a;temp.m_b=p1.m_b+p2.m_b;returntemp;}voidtest01(){Personp1(10,10);Personp2(20,20);Personp3=p1+p2;//Personp3=operator+(p1,p2);//全局函数本质//Personp3=p1.operator+(p2);//全局函数本质//不影响inta=0,b=3;intc=a+b;cout<<"c="<<c<<endl;cout<<"p3.m_a="<<p3.m_a<<"p3.m_b="<<p3.m_b<<endl;}左移运算符<<全局本质是用operator<<(ostream&cout,Person&p)替代cout<<"m_a="<<p.m_a<<"m_b="<<p.m_b;即运算符前后数据替代类本质是本类在前,其他在后的本质,如p1.operator(ostream&cout);这处之所以不能用,cout在后边了classPerson{friendostream&operator<<(ostream&cout,Person&p);public:Person(inta,intb){this->m_a=a;this->m_b=b;};//voidoperator<<(Person&p)//p.operator<<(cout)p<<cout//{//}~Person(){};private:intm_a;intm_b;};//利用全局函数实现左移运算符ostream&operator<<(ostream&cout,Person&p)//{cout<<"m_a="<<p.m_a<<"m_b="<<p.m_b;returncout;}voidtest01(){Personp1(10,15);cout<<p1<<endl;}前置++后置++重载前置递增:MyInter&operator++();MyInteroperator++(int);后置递增:classMyInter{friendostream&operator<<(ostream&cout,MyInter&myint);public:MyInter(){this->m_num=0;};//前置++重载MyInter&operator++(){++this->m_num;return*this;}//后置++重载MyInteroperator++(int)//加int占位编译器自动识别{//先记录初始状态MyIntertemp=*this;this->m_num++;returntemp;}~MyInter(){};private:intm_num;/*intm_temp;*/};ostream&operator<<(ostream&cout,MyInter&myint){cout<<myint.m_num;returncout;}voidtest01(){MyIntermy_inter;cout<<++(++my_inter)<<endl;cout<<my_inter<<endl;my_inter++;//cout<<my_inter++<<endl;}指针运算符重载智能指针,本质是存在堆空间,利用栈自动释放本身,释放堆空间,减小栈空间的使用classPerson{public:Person(intage){cout<<"Person的有参构造调用"<<endl;this->m_age=age;}voidShowAge(){cout<<"年龄为:"<<this->m_age<<endl;}~Person(){cout<<"Person的析构调用"<<endl;}private:intm_age;};classSmartPoint{public:SmartPoint(Person*person){this->m_person=person;}~SmartPoint(){if(this->m_person){deletethis->m_person;this->m_person=NULL;}}//重载->运算符Person*operator->(){returnthis->m_person;}//重载*运算符Person&operator*(){return*m_person;}//Personoperator*()//直接返回值针是拷贝构造//{//return*m_person;//}private:Person*m_person;};voidtest01(){//Person*p=newPerson(18);//(*p).ShowAge();//p->ShowAge();//deletep;//利用智能指针管理new出来的person的释放操作SmartPointsp(newPerson(18));sp->ShowAge();//本质sp->->ShowAge();(*sp).ShowAge();}赋值运算符重载classPerson{public:Person(){};Person(constchar*name,intage){this->m_name=newchar[strlen(name)+1];strcpy(this->m_name,name);this->m_age=age;}Person(constPerson&p){this->m_name=newchar[strlen(p.m_name)+1];strcpy(this->m_name,p.m_name);this->m_age=p.m_age;}//重载=Person&operator=(constPerson&p){//先判断原来堆区是否有内容,有先释放if(this->m_name!=NULL){delete[]this->m_name;this->m_name=NULL;}this->m_name=newchar[strlen(p.m_name)+1];strcpy(this->m_name,p.m_name);this->m_age=p.m_age;return*this;}~Person(){if(this->m_name!=NULL){delete[]this->m_name;this->m_name=NULL;}}char*m_name;intm_age;private:};//编译器默认给一个类添加了4个函数默认构造析构拷贝构造(值拷贝)operatorvoidtest01(){Personp1("Tom",10);p1.m_age=10;//Personp2=p1;//拷贝构造函数Personp2("Jerry",19);p2=p1;cout<<p2.m_name<<endl;cout<<p2.m_age<<endl;Personp3("Jerry",19);p3=p2=p1;//这是赋值Personp4=p3;//这是拷贝构造cout<<p3.m_name<<endl;cout<<p3.m_age<<endl;}[]重载int&operator[](intindex);//index为索引值int&operator[](intindex){returnthis->pAddress[index];}arr[0]=1000;//左值时得返回有空间的值,即引用关系运算符很重要小技巧:返回值是bool类型可以return(this->m_name==p.m_name&&this->m_age==p.m_age);//替代下边判断//if(this->m_name==p.m_name&&this->m_age==p.m_age)//{//returntrue;//}//returnfalse;//关系运算符classPerson{public:Person(){};Person(stringname,intage){this->m_name=name;this->m_age=age;}booloperator==(Person&p){return(this->m_name==p.m_name&&this->m_age==p.m_age);//替代下边判断//if(this->m_name==p.m_name&&this->m_age==p.m_age)//{//returntrue;//}//returnfalse;}booloperator!=(Person&p){return!(this->m_name==p.m_name&&this->m_age==p.m_age);}~Person(){};stringm_name;intm_age;private:};voidtest01(){inta=10;intb=20;if(a==b){cout<<"a==b"<<endl;}else{cout<<"a!=b"<<endl;}Personp1("TOM",18);Personp2("TOM",18);if(p1==p2){cout<<"p1==p2"<<endl;}else{cout<<"p1!=p2"<<endl;}if(p1!=p2){cout<<"p1!=p2"<<endl;}else{cout<<"p1==p2"<<endl;}}函数调用运算符重载MyAdd()(1,1)//匿名函数对象仿函数实际重载()classMyPrint{public:MyPrint(){};voidoperator()(stringtext){cout<<text<<endl;}~MyPrint(){};private:};voidtest01(){MyPrintmy_printf;my_printf("helloworld");//仿函数,函数对象}classMyAdd{public:MyAdd(){};intoperator()(inta,intb){returna+b;}~MyAdd(){};private:};voidtest02(){MyAddmy_add;cout<<my_add(1,1)<<endl;cout<<MyAdd()(1,1)<<endl;//匿名函数对象,当前行执行完自动释放}不要重载逻辑运算符&&和||因为有短路特性&&左边为假右边将不计算||左边为真右边不用算0&&11||0无法重载原有预期,会与运算优先级结合会影响到左边

十九、强化训练字符封装

MyString.h#pragmaonce#define_CRT_SECURE_NO_WARNINGS#include<iostream>usingnamespacestd;classMyString{//重载左移运算符friendostream&operator<<(ostream&cout,MyString&str);//重载右移运算符friendistream&operator>>(istream&cin,MyString&str);public:MyString();MyString(constchar*str);MyString(constMyString&str);//重载=运算符MyString&operator=(constchar*str);MyString&operator=(constMyString&str);//重载运算符[]char&operator[](intindex);//重载+运算符MyStringoperator+(constchar*str);MyStringoperator+(constMyString&str);//重载==booloperator==(constchar*str);booloperator==(constMyString&str);~MyString();private:char*pString;//维护在堆区开辟的字符数组intm_size;//字符串长度不统计\0};MyString.cpp#include"MyString.h"MyString::MyString(){}MyString::MyString(constchar*str){/*cout<<"有参构造函数调"<<endl;*/this->pString=newchar[strlen(str)+1];strcpy(this->pString,str);this->m_size=strlen(str);}MyString::MyString(constMyString&str){/*cout<<"拷贝构造函数调"<<endl;*/this->pString=newchar[strlen(str.pString)+1];strcpy(this->pString,str.pString);this->m_size=str.m_size;}MyString&MyString::operator=(constchar*str){//先判断原来堆区释放原有内容,如果有先释放if(this->pString!=NULL){delete[]this->pString;this->pString=NULL;}this->pString=newchar[strlen(str)+1];strcpy(this->pString,str);this->m_size=strlen(str);return*this;}MyString&MyString::operator=(constMyString&str){if(this->pString!=NULL){delete[]this->pString;this->pString=NULL;}this->pString=newchar[strlen(str.pString)+1];strcpy(this->pString,str.pString);this->m_size=str.m_size;return*this;}char&MyString::operator[](intindex){returnthis->pString[index];}MyStringMyString::operator+(constchar*str){intNewSize=this->m_size+strlen(str)+1;char*temp=newchar[NewSize];memset(temp,0,NewSize);strcat(temp,this->pString);strcat(temp,str);MyStringNewString=temp;delete[]temp;returnNewString;}MyStringMyString::operator+(constMyString&str){intNewSize=this->m_size+strlen(str.pString)+1;char*temp=newchar[NewSize];memset(temp,0,NewSize);strcat(temp,this->pString);strcat(temp,str.pString);MyStringNewString=temp;delete[]temp;returnNewString;}boolMyString::operator==(constchar*str){/*return(this->pString==str);*///不可以return(strcmp(this->pString,str)==0);}boolMyString::operator==(constMyString&str){return(strcmp(this->pString,str.pString)==0);}MyString::~MyString(){/*cout<<"析构函数调"<<endl;*/if(this->pString!=NULL){delete[]this->pString;}}ostream&operator<<(ostream&cout,MyString&str){cout<<str.pString;returncout;}istream&operator>>(istream&cin,MyString&str){if(str.pString!=NULL)//if(str.pString){delete[]str.pString;str.pString=NULL;}charbuf[1024];cin>>buf;str.pString=newchar[strlen(buf)+1];strcpy(str.pString,buf);str.m_size=strlen(buf);returncin;}test.cpp#define_CRT_SECURE_NO_WARNINGS#include<iostream>#include"MyString.h"usingnamespacestd;voidtest01(){MyStringstr="arr";MyStringstr2=str;cout<<str<<endl;cout<<"请重新给str赋值"<<endl;cin>>str;cout<<"str新的值"<<str<<endl;}voidtest02(){MyStringstr="arr";MyStringstr2="aaa";str2=str;cout<<"str2="<<str2<<endl;str2[0]='z';cout<<str2[0]<<endl;MyStringstr3="abc";MyStringstr4="def";MyStringstr5=str3+str4;MyStringstr6=str3+str4+str5;cout<<"str5:"<<str5<<endl;cout<<"str6:"<<str6<<endl;if(str5==str6){cout<<"str5==str6"<<endl;}else{cout<<"str5!=str6"<<endl;}str6="abcd";if(str6=="abcd"){cout<<"str6=="<<endl;}else{cout<<"!=str6"<<endl;}}intmain(intargc,char*argv[]){test02();system("pause");returnEXIT_SUCCESS;}

二十、继承

#include<iostream>usingnamespacestd;//classNews//{//public:////voidheader()//{//cout<<"公共的头部"<<endl;//}////voidfooter()//{//cout<<"公共的底部"<<endl;//}////voidleftList()//{//cout<<"公共左侧列表"<<endl;//}////voidcontent()//{//cout<<"新闻播报..."<<endl;//}//};//利用继承模拟网页//继承优点:减少重复代码,提高代码复用性//子类可以访问:publicprotected不可访问:privateclassBasePage{public:voidheader(){cout<<"公共的头部"<<endl;}voidfooter(){cout<<"公共的底部"<<endl;}voidleftList(){cout<<"公共左侧列表"<<endl;}};classNews:publicBasePage{public:voidcontent(){cout<<"新闻播报..."<<endl;}};classSport:publicBasePage{public:voidcontent(){cout<<"世界杯..."<<endl;}};voidtest01(){Newsnews;cout<<"新闻页面为:"<<endl;news.header();news.footer();news.leftList();news.content();}

#include<iostream>usingnamespacestd;/********************公共继承********************/classBase1{/*friendclassSon1;*///子类可以作为父类的友元public:intm_a;protected:intm_b;private:intm_c;};classSon1:publicBase1{public:voidfunc(){m_a=100;//父类中公共权限子类中变为公共权限m_b=100;//父类中保护权限子类中变为保护权限//m_c=100;//父类中私有成员,子类无法访问}};voidtest01(){Son1s1;s1.m_a=100;/*s1.m_b=100;*///在类外不可访问}/********************保护继承********************/classBase2{public:intm_a;protected:intm_b;private:intm_c;};classSon2:protectedBase2{public:voidfunc(){m_a=100;//父类中公共权限子类中变为公共权限m_b=100;//父类中保护权限子类中变为保护权限//m_c=100;//父类中私有成员,子类无法访问}};voidtes02(){Son2s2;//父类继承过来的全变成保护权限/*s1.m_a=100;*///在类外不可访问/*s1.m_b=100;*///在类外不可访问}/********************私有继承********************/classBase3{public:intm_a;protected:intm_b;private:intm_c;};classSon3:privateBase3{public:voidfunc(){m_a=100;//父类中公共权限子类中变为公共权限m_b=100;//父类中保护权限子类中变为保护权限//m_c=100;//父类中私有成员,子类无法访问}};voidtes03(){Son3s3;//父类继承过来的全变成私有权限/*s1.m_a=100;*///在类外不可访问/*s1.m_b=100;*///在类外不可访问}classGrandSon3:publicSon1//Son1Son2可以继承因为父类是公共权限和保护权限//Son3不能是私有权限{public:voidfunc(){m_a=100;}};intmain(intargc,char*argv[]){system("pause");returnEXIT_SUCCESS;}

继承中的对象父类的私有属性,子类是继承下去了,只不过是编译器给隐藏了,访问不到可以利用开发人员工具查看对象模型D:\ProgramFiles(x86)\MicrosoftVisualStudio14.0\Common7\Tools打开开发人员命令工具跳转盘符D:跳转文件路径cd\ProgramFiles(x86)\MicrosoftVisualStudio14.0\Common7\Toolscl/d1reportSingleClassLayou类名继承中的构造和析构//先调用父类构造,再调用其他成员构造,再构造自身//先调用父类构造,再调用其他成员构造,再构造自身//子类继承默认调用父类无参构造函数,如父类定义有参构造,父类需定义无参构造函数或者子类用列表初始化//父类中的默认构造、析构、拷贝构造、operator=是不会被子类继承下去,但是会调用#include<iostream>usingnamespacestd;classBase1{public:Base1(){cout<<"Base1的构造函数调用"<<endl;}~Base1(){cout<<"Base1的析构函数的调用"<<endl;}};classOther{public:Other(){cout<<"Other的构造函数调用"<<endl;}~Other(){cout<<"Other的析构函数的调用"<<endl;}};classSon1:publicBase1{public:Son1(){cout<<"Son1的构造函数调用"<<endl;}~Son1(){cout<<"Son1的析构函数的调用"<<endl;}Otherother;};voidtest01(){Son1s;//先调用父类构造,再调用其他成员构造,再构造自身}classBase2{public:Base2(inta){this->m_a=a;cout<<"Base2的构造函数调用"<<endl;}intm_a;};//子类继承默认调用父类无参构造函数,如父类定义有参构造,父类需定义无参构造函数//或者子类用列表初始化classSon2:publicBase2{public:Son2(inta):Base2(a)//利用初始化列表语法显示调用父类中的其他构造函数{cout<<"Son2的构造函数调用"<<endl;}};voidtest02(){Son2s(100);cout<<s.m_a<<endl;}//父类中的默认构造、析构、拷贝构造、operator=是不会被子类继承下去,但是会调用intmain(intargc,char*argv[]){test02();system("pause");returnEXIT_SUCCESS;}继承中同名成员处理//1.我们可以利用作用域访问父类的同名成员//2.当子类重新定义了父类中的同名成员函数,子类的成员函数会隐藏掉父类中所有的重载版本可以用作用域访问#include<iostream>usingnamespacestd;classBase{public:Base(){this->m_a=10;}voidfunc(){cout<<"func父类调用"<<endl;}voidfunc(inta){cout<<"func(inta)调用"<<endl;}intm_a;};classSon:publicBase{public:Son(){this->m_a=20;}voidfunc(){cout<<"func子类调用"<<endl;}intm_a;};voidtest01(){Sons1;cout<<"s1.m_a="<<s1.m_a<<endl;//我们可以用作用域访问父类中的同名成员cout<<"Base中的m_a="<<s1.Base::m_a<<endl;}voidtest02(){Sons1;s1.func();s1.Base::func();/*s1.func(10);*///不能用//当子类重新定义了父类中的同名成员函数,子类的成员函数会隐藏掉父类中所有的重载版本//可以用作用域访问//改为s1.Base::func(10);}intmain(intargc,char*argv[]){test02();system("pause");returnEXIT_SUCCESS;}继承中的同名的静态成员当子类重定义父类中同名的成员函数,子类的成员函数会隐藏掉父类中的所有版本,需要加作用域调用#include<iostream>usingnamespacestd;classBase{public:staticvoidfunc()//没有this指针{cout<<"Base中的func()调用"<<endl;}staticvoidfunc(inta)//没有this指针{cout<<"父类中的func(inta)调用"<<endl;}staticintm_a;};intBase::m_a=10;classSon:publicBase{public:staticvoidfunc()//没有this指针{cout<<"子类中的func()调用"<<endl;}staticvoidfunc(inta)//没有this指针{cout<<"子类中的func(inta)调用"<<endl;}staticintm_a;};intSon::m_a=20;//测试继承静态同名成员变量voidtest01(){//1.通过对象访问Sons;cout<<"m_a="<<s.m_a<<endl;cout<<"Basem_a="<<s.Base::m_a<<endl;//2.通过类名访问cout<<"m_a="<<Son::m_a<<endl;cout<<"Basem_a="<<Base::m_a<<endl;//通过类名的方式从子类到父类访问cout<<"Basem_a="<<Son::Base::m_a<<endl;}//测试继承静态同名成员函数//当子类重定义父类中同名的成员函数,子类的成员函数会隐藏掉父类中的所有版本,需要加作用域调用voidtest02(){//1.通过对象访问Sons;s.func();s.Base::func();//2.通过类名访问Son::func();Base::func();Son::Base::func();Son::func(1);//当子类重定义父类中同名的成员函数,子类的成员函数会隐藏掉父类中的所有版本,需要加作用域调用Son::Base::func(1);}intmain(intargc,char*argv[]){test02();system("pause");returnEXIT_SUCCESS;}

继承的概念 多继承

vbptrv-virtual虚拟bbase基础ptrpointer指针//vbtable虚基类表,加上virtual实质是通过指针在虚基类表上偏移,找到同一指向地址classA:publicB1,publicB2#include<iostream>usingnamespacestd;//动物类//Animal称为虚基类classAnimal{public:intm_age;//年龄};//羊类classSheep:virtualpublicAnimal{public:};//驼类classTuo:virtualpublicAnimal{public:};//驼类虚继承classSheepTuo:publicSheep,publicTuo{};voidtest01(){SheepTuost;st.Sheep::m_age=10;st.Tuo::m_age=20;cout<<"shee::m_age="<<st.Sheep::m_age<<endl;cout<<"shee::m_age="<<st.Tuo::m_age<<endl;cout<<"shee::m_age="<<st.m_age<<endl;//当虚继承后,sheep和tuo类中继承了一个vbptr指针虚基类指针指向的是一个虚基类表vbtable//虚基类表中记录了偏移量,通过偏移量可以找到唯一的一个m_age}voidtest02(){SheepTuost;st.m_age=10;//通过Sheep找到偏移量//*(int*)&st解引用到了虚基类表中cout<<*((int*)*(int*)&st+1)<<endl;//通过tuo找到偏移量cout<<*((int*)*((int*)&st+1)+1)<<endl;//通过偏移量访问m_agecout<<"m_age="<<((Animal*)((char*)&st+*((int*)*(int*)&st+1)))->m_age<<endl;cout<<"m_age="<<*((int*)((char*)&st+*((int*)*(int*)&st+1)))<<endl;}intmain(intargc,char*argv[]){test02();system("pause");returnEXIT_SUCCESS;}

视频链接/video/BV1kV411U7Ub?spm_id_from=333.999.0.0

建议用python或者浏览器视频插件把视频先下下来,万一没了呢!!!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。