C++基础2 引用 函数扩展: 默认值 占位符 指针 重载 类:引用类指针 声明实现分开写
【难点】指针引用
chunli@Linux:~/c++$catmain.cpp#include<stdlib.h>#include"iostream"usingnamespacestd;inta=20;structTeacher{intage;charname[64];};intfun1(structTeacher**p){intret=0;if(p==NULL){ret=-1;returnret;}Teacher*tmp=(Teacher*)malloc(sizeof(structTeacher));tmp->age=20;*p=tmp;//p的值是一个地址,*p就是修改这个地址里面的值returna;}intfun2(structTeacher*&p){//这里的p就是主函数的pintret=0;if(p==NULL){ret=-1;returnret;}p=(structTeacher*)malloc(sizeof(structTeacher));p->age=30;}voidfun3(structTeacher*p){if(p==NULL){return;}free(p);}intmain(){structTeacher*p=NULL;fun1(&p);cout<<p->age<<endl;fun3(p);fun2(p);cout<<p->age<<endl;fun3(p);//此时编译器已经帮我们取地址了return0;}chunli@Linux:~/c++$g++main.cpp&&./a.out2030chunli@Linux:~/c++$
【常引用基础】
让变量引用只读属性,不能再修改变量的值了
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;intmain(){inta=10;constint&b=a;b=20;return0;}chunli@Linux:~/c++$g++main.cpp&&./a.outmain.cpp:Infunction‘intmain()’:main.cpp:8:4:error:assignmentofread-onlyreference‘b’b=20;^
【常引用的初始化1】
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;intmain(){inta=10;constint&b=a;cout<<b<<endl;return0;}chunli@Linux:~/c++$g++main.cpp&&./a.out10
常引用初始化2,用字面量初始化常量·常量引用
这样写编译不通过
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;intmain(){inta=10;int&b=11;//引用的是一个字面量cout<<b<<endl;return0;}chunli@Linux:~/c++$g++main.cpp&&./a.outmain.cpp:Infunction‘intmain()’:main.cpp:6:11:error:invalidinitializationofnon-constreferenceoftype‘int&’fromanrvalueoftype‘int’int&b=11;^
修改一下,就可以啦
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;intmain(){inta=10;constint&b=11;//C++编译器会分配内存空间cout<<b<<endl;return0;}chunli@Linux:~/c++$g++main.cpp&&./a.out11
常引用初始化2常量引用做函数参数,
让实参拥有只读属性
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;//相当于constint*constaintfun(constint&a){cout<<a<<endl;}intmain(){inta=10;fun(a);return0;}chunli@Linux:~/c++$g++main.cpp&&./a.out10
【内联函数】
说明1:
必须inline int myfunc(int a,int b)和函数体的实现,写在一块
说明2
C++编译器可以将一个函数进行内联编译
被C++编译器内联编译的函数叫做内联函数
内联函数在最终生成的代码中是没有定义的
C++编译器直接将函数体插入在函数调用的地方
内联函数没有普通函数调用时的额外开销(压栈,跳转,返回)
说明3:C++编译器不一定准许函数的内联请求!
说明4
内联函数是一种特殊的函数,具有普通函数的特征(参数检查,返回类型等)
内联函数是对编译器的一种请求,因此编译器可能拒绝这种请求
内联函数由编译器处理,直接将编译后的函数体插入调用的地方
宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程
说明5:
现代C++编译器能够进行编译优化,因此一些函数即使没有inline声明,也可能被编译器内联编译
另外,一些现代C++编译器提供了扩展语法,能够对函数进行强制内联
如:g++中的__attribute__((always_inline))属性
说明6:
C++中内联编译的限制:
不能存在任何形式的循环语句
不能存在过多的条件判断语句
函数体不能过于庞大
不能对函数进行取址操作
函数内联声明必须在调用语句之前
编译器对于内联函数的限制并不是绝对的,内联函数相对于普通函数的优势只是省去了函数调用时压栈,跳转和返回的开销。
因此,当函数体的执行开销远大于压栈,跳转和返回所用的开销时,那么内联将无意义。
结论:
1)内联函数在编译时直接将函数体插入函数调用的地方
2)inline只是一种请求,编译器不一定允许这种请求
3)内联函数省去了普通函数调用时压栈,跳转和返回的开销
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;inlinevoidfun(){cout<<"HelloWorld!"<<endl;}intmain(){fun();return0;}chunli@Linux:~/c++$g++main.cpp&&./a.outHelloWorld!
带参数的宏
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;//带参数的宏.谨慎带有++--的参数#defineFUN(a,b)((a)<(b)?(a):(b))inlineintfun(inta,intb){returna<b?a:b;}intmain(){intvar1=1;intvar2=3;inta=FUN(++var1,var2++);cout<<a<<endl;a=fun(++var1,var2++);cout<<a<<endl;return0;}chunli@Linux:~/c++$g++main.cpp&&./a.out34
函数默认值:
默认参数要么全部都有,要么只在右边
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;intfun(inta,intb=4){cout<<a<<""<<b<<endl;}intmain(){fun(1);return0;}chunli@Linux:~/c++$g++main.cpp&&./a.out14
如果默认参数在前面,后面也有参数但是没有默认参数,编译报错
默认参数应该在函数的右边
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;intfun(inta=1,intb){cout<<a<<""<<b<<endl;}intmain(){fun(1,2);return0;}chunli@Linux:~/c++$g++main.cpp&&./a.outmain.cpp:Infunction‘intfun(int,int)’:main.cpp:4:5:error:defaultargumentmissingforparameter2of‘intfun(int,int)’intfun(inta=1,intb)^
函数占位参数
调用时,必须写够参数
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;intfun(inta,intb,int){cout<<a<<"";cout<<b<<endl;}intmain(){fun(1,2,4);return0;}chunli@Linux:~/c++$g++main.cpp&&./a.out12
默认参数 与 占位符在一起
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;//默认参数与占位符在一起voidfun(inta,intb,int=0){cout<<a<<"";cout<<b<<endl;}intmain(){fun(3,2);fun(1,2,4);return0;}chunli@Linux:~/c++$g++-Wall-gmain.cpp&&./a.out3212
函数重载:【面试重点】
函数名必须一致
函数返回值类型必须一致
函数的实参类型不一致
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;intfun(inta){cout<<a<<"\n";return1;}intfun(int*p){cout<<*p<<"\n";return2;}intfun(inta,intb){cout<<a<<"";cout<<b<<endl;return3;}intmain(){fun(1);fun(3,2);inta=40;fun(&a);return0;}chunli@Linux:~/c++$g++-Wall-gmain.cpp&&./a.out13240
当函数重载遇到默认参数,C++编译器不允许通过,编译失败
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;intfun(inta,intb){cout<<a<<"";cout<<b<<endl;return1;}intfun(inta,intb,intc=0){cout<<a<<"";cout<<b<<"";cout<<c<<endl;return2;}intmain(){fun(3,2);return0;}chunli@Linux:~/c++$g++-Wall-gmain.cpp&&./a.outmain.cpp:Infunction‘intmain()’:main.cpp:21:9:error:callofoverloaded‘fun(int,int)’isambiguousfun(3,2);^
当存在二义性的重载函数,你不去调用,编译器就不会报错:
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;intfun(inta){cout<<a<<endl;return1;}intfun(inta,intb){cout<<a<<"";cout<<b<<endl;return1;}intfun(inta,intb,intc=0){cout<<a<<"";cout<<b<<"";cout<<c<<endl;return2;}intmain(){fun(3);return0;}chunli@Linux:~/c++$g++-Wall-gmain.cpp&&./a.out3
函数指针的申明:三种方式:
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;//申明一个函数的数据类型typedefvoid(fun1)(inta,intb);//自定义一个数据类型//申明一个函数的数据类型typedefvoid(*fun2)(inta,intb);//申明了一个指针的数据类型//定义一个函数指针的变量void(*fun3)(inta,intb);intmain(){fun1*p1=NULL;//定义一个函数指针,指向函数的入口地址fun2p2=NULL;//定义一个函数指针,指向函数的入口地址return0;}chunli@Linux:~/c++$g++-gmain.cpp&&./a.out
当函数重载与函数指针在一起
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;voidfun(inta,intb){cout<<a<<endl;cout<<b<<endl;}voidfun(inta){cout<<a<<endl;}intmain(){typedefvoid(*p_fun)(inta,intb);//申明了一个指针的数据类型p_funp=NULL;//定义一个函数指针,指向函数的入口地址p=fun;p(1,3);//p(3);//会报错return0;}chunli@Linux:~/c++$g++-gmain.cpp&&./a.out13
=========C++ 对C 的扩展 结束=============
【类的初步】
类的初步:
类是抽象的,并没有内存空间
对象是具体的
计算圆的面积:
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;classMycricle{public:doublem_r;doublem_s;public:doubleset_r(doubler){m_r=r;}doubleget_r(){returnm_r;}doubleget_s(){m_s=3.14*m_r*m_r;returnm_s;}};intmain(){Mycriclec1,c2;c1.set_r(10);cout<<c1.get_s()<<endl;c2.set_r(1);cout<<c2.get_s()<<endl;return0;}chunli@Linux:~/c++$g++-gmain.cpp&&./a.out3143.14
【封装的含义1】
类的威力,用类当函数的参数:
比原来的结构体功能强大很多!
1,类指针
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;classMycricle{public:doublem_r;doublem_s;public:voidset_r(doubler){m_r=r;}doubleget_r(){returnm_r;}doubleget_s(){m_s=3.14*m_r*m_r;returnm_s;}};voidfun(Mycricle*p){cout<<"r="<<p->get_r();cout<<"s="<<p->get_s()<<endl;}intmain(){Mycriclec1,c2;c1.set_r(10);fun(&c1);c2.set_r(1);fun(&c2);return0;}chunli@Linux:~/c++$g++-Wall-gmain.cpp&&./a.outr=10s=314r=1s=3.14chunli@Linux:~/c++$
【封装的含义1】
类的威力,用类当函数的参数:
比原来的结构体功能强大很多!
1,类引用
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;classMycricle{public:doublem_r;doublem_s;public:voidset_r(doubler){m_r=r;}doubleget_r(){returnm_r;}doubleget_s(){m_s=3.14*m_r*m_r;returnm_s;}};voidfun(Mycricle&p){cout<<"r="<<p.get_r();cout<<"s="<<p.get_s()<<endl;}intmain(){Mycriclec1,c2;c1.set_r(10);fun(c1);c2.set_r(1);fun(c2);return0;}chunli@Linux:~/c++$g++-Wall-gmain.cpp&&./a.outr=10s=314r=1s=3.14
类的控制:
public 修饰的成员变量和函数,可以在类的内部和类的外部访问
private 修饰的成员变量和函数,只能可以在类的内部访问,不能在类的外部访问
private 修饰的成员变量和函数,只能可以在类的内部访问,不能在类的外部访问
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;classMycricle{private:doublem_r;doublem_s;public:voidset_r(doubler){m_r=r;}doubleget_r(){returnm_r;}doubleget_s(){m_s=3.14*m_r*m_r;returnm_s;}};voidfun(Mycricle&p){cout<<"r="<<p.get_r();cout<<"s="<<p.get_s()<<endl;}intmain(){Mycriclec1,c2;c1.set_r(10);fun(c1);c2.set_r(1);fun(c2);c1.m_r=10;return0;}chunli@Linux:~/c++$g++-Wall-gmain.cpp&&./a.outmain.cpp:Infunction‘intmain()’:main.cpp:7:9:error:‘doubleMycricle::m_r’isprivatedoublem_r;^提示这是一个private类型
默认属性就是私有属性
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;classMycricle{intage;//默认清空下,这是一个私有属性};intmain(){Mycriclec;c.age=10;return0;}chunli@Linux:~/c++$g++-Wall-gmain.cpp&&./a.outmain.cpp:Infunction‘intmain()’:main.cpp:6:6:error:‘intMycricle::age’isprivateintage;//默认清空下,这是一个私有属性^
在c++中结构体的默认属性的public
chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;structtest{intage;//默认清空下,是public属性};intmain(){testt1;t1.age=10;return0;}chunli@Linux:~/c++$catmain.cpp#include"iostream"usingnamespacestd;structtest{intage;//默认清空下,是public属性};intmain(){testt1;t1.age=10;cout<<t1.age<<endl;return0;}chunli@Linux:~/c++$g++-Wall-gmain.cpp&&./a.out10
类的申明与实现,分开:
1主函数
chunli@Linux:~/c++$catmain.cpp#include"teacher.h"#include"iostream"usingnamespacestd;intmain(){teachert1;t1.set_age(36);cout<<(t1.get_age())<<"\n";return0;}
2类的声明
chunli@Linux:~/c++$catteacher.h#pragmaonce#ifndef__TEACHER_H_#define__TEACHER_H_classteacher{private:intage;charname[32];public:voidset_age(inta);intget_age();};#endif
3,类的实现
chunli@Linux:~/c++$catteacher.cpp#include"teacher.h"voidteacher::set_age(inta){age=a;}intteacher::get_age(){returnage;}
编译运行
chunli@Linux:~/c++$g++-gmain.cppteacher.cpp&&./a.out36
转变到面向对象转变过程
chunli@Linux:~/c++$catmycube.cpp#include<iostream>usingnamespacestd;classCube{public:voidset_abc(inta=0,intb=0,intc=0){m_a=a;m_b=b;m_c=c;}intget_v(){m_v=m_a*m_b*m_c;returnm_v;}intget_s(){m_s=2*((m_a*m_b)+(m_a*m_c)+(m_b*m_c));returnm_s;}private:intm_a;intm_b;intm_c;intm_v;intm_s;};intmain(){Cubev1;v1.set_abc(1,1,1);cout<<"体积="<<v1.get_v()<<endl;cout<<"面积="<<v1.get_s()<<endl;return0;}chunli@Linux:~/c++$g++-Wall-gmycube.cpp&&./a.out体积=1面积=6
加料啦!
比较两个立方体的是否一样
1,用外部函数来比较
chunli@Linux:~/c++$catmycube.cpp#include<iostream>usingnamespacestd;classCube{public:voidset_abc(inta=0,intb=0,intc=0){m_a=a;m_b=b;m_c=c;}intget_v(){m_v=m_a*m_b*m_c;returnm_v;}intget_s(){m_s=2*((m_a*m_b)+(m_a*m_c)+(m_b*m_c));returnm_s;}intget_a(){returnm_a;}intget_b(){returnm_b;}intget_c(){returnm_c;}private:intm_a;intm_b;intm_c;intm_v;intm_s;};intmain(){Cubev1;v1.set_abc(1,1,1);Cubev2;v2.set_abc(1,1,3);if(v1.get_a()==v2.get_a()&&v1.get_b()==v2.get_b()&&v1.get_c()==v2.get_c()){cout<<"equal\n";}else{cout<<"notequal\n";}return0;}chunli@Linux:~/c++$g++-Wall-gmycube.cpp&&./a.outnotequal
用面向对象的方式 实现立方体的比较
chunli@Linux:~/c++$catmycube.cpp#include<iostream>usingnamespacestd;classCube{public:voidset_abc(inta=0,intb=0,intc=0){m_a=a;m_b=b;m_c=c;}intget_v(){m_v=m_a*m_b*m_c;returnm_v;}intget_s(){m_s=2*((m_a*m_b)+(m_a*m_c)+(m_b*m_c));returnm_s;}intget_a(){returnm_a;}intget_b(){returnm_b;}intget_c(){returnm_c;}intjudge(Cube&v){//cout<<"m_a="<<m_a<<"";//cout<<"m_b="<<m_b<<"";//cout<<"m_c="<<m_c<<"\n";//cout<<"get_a="<<v.get_a()<<"";//cout<<"get_b="<<v.get_b()<<"";//cout<<"get_c="<<v.get_c()<<"\n";if(m_a==v.get_a()&&m_b==v.get_b()&&m_c==v.get_c()){return1;}else{return0;}}private:intm_a;intm_b;intm_c;intm_v;intm_s;};intmain(){Cubev1;v1.set_abc(1,1,1);Cubev2;v2.set_abc(1,1,1);if(v1.judge(v2)==1){cout<<"equal\n";}else{cout<<"notequal\n";}return0;}chunli@Linux:~/c++$g++-Wall-gmycube.cpp&&./a.outequal
用面向对象的思路求【点】是否在【圆】内
涉及到两个类,一个是点,一个是圆
源代码:
chunli@Linux:~/c++$catmycube.cpp#include<iostream>usingnamespacestd;//classMyPoint;这是类的前置申明classMyPoint{public:intget_x(){returnx1;}intget_y(){returny1;}voidsetPoint(int_x1,int_y1){x1=_x1;y1=_y1;}private:intx1;inty1;};classadvCircle{public:voidsetCircle(int_r,int_x0,int_y0){r=_r;x0=_x0;y0=_y0;}intjudge(MyPoint&p){intl=(p.get_x()-x0)*(p.get_y()-y0);if(r*r>l){return1;}else{return0;}}private:intr;intx0;inty0;};intmain(){advCirclec1;c1.setCircle(2,3,3);MyPointp1;p1.setPoint(7,7);if(c1.judge(p1)==1){cout<<"在圆内\n";}else{cout<<"在圆外\n";}return0;}chunli@Linux:~/c++$g++-Wall-gmycube.cpp&&./a.out在圆外
把类的申明与实现分开写:
有这么5个文件:
chunli@Linux:~/c++$lltotal20K-rw-rw-r--1chunlichunli347Jun2816:46advCircle.cpp-rw-rw-r--1chunlichunli253Jun2816:49advCircle.h-rw-rw-r--1chunlichunli263Jun2816:50main.cpp-rw-rw-r--1chunlichunli172Jun2816:39MyPoint.cpp-rw-rw-r--1chunlichunli215Jun2816:42MyPoint.h
文件1:
chunli@Linux:~/c++$catadvCircle.h#pragmaonce#include"MyPoint.h"#ifndef__ADVCIRCLE_H_#define__ADVCIRCLE_H_classadvCircle{public:voidsetCircle(int_r,int_x0,int_y0);intjudge(MyPoint&p);private:intr;intx0;inty0;};#endif
文件2:
chunli@Linux:~/c++$catadvCircle.cpp#include"advCircle.h"voidadvCircle::setCircle(int_r,int_x0,int_y0){r=_r;x0=_x0;y0=_y0;}intadvCircle::judge(MyPoint&p){intl=(p.get_x()-x0)*(p.get_y()-y0);if(r*r>l){return1;}else{return0;}}
文件3:
chunli@Linux:~/c++$catMyPoint.h#pragmaonce#ifndef__MYPOINT_H_#define__MYPOINT_H_classMyPoint{private:intx1;inty1;public:intget_x();intget_y();voidsetPoint(int_x1,int_y1);};#endif
文件4:
chunli@Linux:~/c++$catMyPoint.cpp#include"MyPoint.h"intMyPoint::get_x(){returnx1;}intMyPoint::get_y(){returny1;}voidMyPoint::setPoint(int_x1,int_y1){x1=_x1;y1=_y1;}
文件5:
chunli@Linux:~/c++$catmain.cpp#include"MyPoint.h"#include"advCircle.h"#include<iostream>usingnamespacestd;intmain(){advCirclec1;c1.setCircle(2,3,3);MyPointp1;p1.setPoint(7,7);if(c1.judge(p1)==1){cout<<"在圆内\n";}else{cout<<"在圆外\n";}return0;}
编译运行:
chunli@Linux:~/c++$g++-gmain.cppMyPoint.cppadvCircle.cpp&&./a.out在圆外
作业:
第1题:
chunli@Linux:~/c++$catmain.cpp#include<iostream>usingnamespacestd;classcricle{private:intr;intx;inty;public:intget_x(){returnx;}intget_y(){returny;}intget_r(){returnr;}voidset_rxy(){cout<<"请输入圆的半径,x,y坐标";cout<<"如142代表半径为1,横坐标为4纵坐标为2\n";cin>>r>>x>>y;}intjudge(criclec){intl=(c.get_x()-x)*(c.get_x()-x)+(c.get_y()-y)*(c.get_y()-y);intd=(r+c.get_r())*(r+c.get_r());if(d==l){return0;}elseif(d>l){return1;}else{return-1;}}};intmain(){criclec1;c1.set_rxy();criclec2;c2.set_rxy();intret=c1.judge(c2);if(ret==0){cout<<"两圆相切\n";}elseif(ret==-1){cout<<"两圆相离\n";}else{cout<<"两圆相交\n";}return0;}chunli@Linux:~/c++$编译运行:chunli@Linux:~/c++$g++-g-Wallmain.cpp&&./a.out请输入圆的半径,x,y坐标如142代表半径为1,横坐标为4纵坐标为2122请输入圆的半径,x,y坐标如142代表半径为1,横坐标为4纵坐标为2132两圆相交chunli@Linux:~/c++$g++-g-Wallmain.cpp&&./a.out请输入圆的半径,x,y坐标如142代表半径为1,横坐标为4纵坐标为2122请输入圆的半径,x,y坐标如142代表半径为1,横坐标为4纵坐标为2142两圆相切chunli@Linux:~/c++$g++-g-Wallmain.cpp&&./a.out请输入圆的半径,x,y坐标如142代表半径为1,横坐标为4纵坐标为2122请输入圆的半径,x,y坐标如142代表半径为1,横坐标为4纵坐标为2152两圆相离
第2题:
chunli@Linux:~/c++$catmain.cpp#include<iostream>usingnamespacestd;classRectangle{private:intx1;inty1;intx2;inty2;ints;public:voidset_xy(int_x1,int_y1,int_x2,int_y2){x1=_x1;y1=_y1;x2=_x2;y2=_y2;}intget_s(){s=(x2-x1)*(y2-y1);returns;}};intmain(){Rectangler1;r1.set_xy(0,0,4,4);cout<<r1.get_s()<<endl;return0;}chunli@Linux:~/c++$g++-g-Wallmain.cpp&&./a.out16
第3题:
chunli@Linux:~/c++$catmain.cpp#include<iostream>usingnamespacestd;classTree{private:intn;public:voidgrow(int_age){n=_age;}intage(){returnn;}};intmain(){Treet1;t1.grow(99);cout<<t1.age()<<endl;return0;}chunli@Linux:~/c++$g++-g-Wallmain.cpp&&./a.out99
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。