【难点】指针引用

chunli@Linux:~/c++$ cat main.cpp #include 
#include "iostream" using namespace std;int a = 20;struct Teacher{ int age; char name[64];};int fun1(struct Teacher ** p){ int ret = 0; if(p == NULL) { ret = -1; return  ret; } Teacher *tmp = (Teacher *)malloc(sizeof(struct  Teacher)); tmp -> age = 20; *p = tmp; // p的值是一个地址,*p就是修改这个地址里面的值 return a;}int fun2(struct Teacher *&p){ //这里的p就是主函数的p int ret = 0; if(p == NULL) { ret = -1; return ret; } p = (struct  Teacher *)malloc(sizeof(struct  Teacher)); p->age = 30;}void fun3(struct Teacher *p){ if(p == NULL) { return ; } free(p);}int main(){ struct Teacher *p = NULL; fun1(&p);cout << p->age << endl;fun3(p); fun2(p);cout << p->age << endl;fun3(p);//此时编译器已经帮我们取地址了 return 0;}chunli@Linux:~/c++$ g++ main.cpp  && ./a.out 2030chunli@Linux:~/c++$

【常引用基础】

让变量引用只读属性,不能再修改变量的值了

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;int main(){	int  a = 10;	const int &b = a;	b = 20;	return 0;}chunli@Linux:~/c++$ g++ main.cpp  && ./a.out main.cpp: In function ‘int main()’:main.cpp:8:4: error: assignment of read-only reference ‘b’  b = 20;    ^

【常引用的初始化1】

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;int main(){	int  a = 10;	const int &b = a;	cout << b << endl;	return 0;}chunli@Linux:~/c++$ g++ main.cpp  && ./a.out 10

常引用初始化2,用字面量初始化常量·常量引用

这样写编译不通过

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;int main(){	int  a = 10;	int &b = 11;	//引用的是一个字面量	cout << b << endl;	return 0;}chunli@Linux:~/c++$ g++ main.cpp  && ./a.out main.cpp: In function ‘int main()’:main.cpp:6:11: error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’  int &b = 11;           ^

修改一下,就可以啦

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;int main(){	int  a = 10;	const int &b = 11;	//	C++编译器会分配内存空间	cout << b << endl;	return 0;}chunli@Linux:~/c++$ g++ main.cpp  && ./a.out 11

常引用初始化2常量引用做函数参数,

让实参拥有只读属性

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;//相当于 const int  * const aint fun(const int &a){	cout<< a <

【内联函数】

说明1

必须inline int myfunc(int a,int b)和函数体的实现,写在一块

说明2

C++编译器可以将一个函数进行内联编译

C++编译器内联编译的函数叫做内联函数

内联函数在最终生成的代码中是没有定义的

C++编译器直接将函数体插入在函数调用的地方

内联函数没有普通函数调用时的额外开销(压栈,跳转,返回)

说明3C++编译器不一定准许函数的内联请求!

说明4

内联函数是一种特殊的函数,具有普通函数的特征(参数检查,返回类型等)

内联函数是对编译器的一种请求,因此编译器可能拒绝这种请求

内联函数由编译器处理,直接将编译后的函数体插入调用的地方

宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程

说明5

现代C++编译器能够进行编译优化,因此一些函数即使没有inline声明,也可能被编译器内联编译

另外,一些现代C++编译器提供了扩展语法,能够对函数进行强制内联

如:g++中的__attribute__((always_inline))属性

说明6

C++中内联编译的限制:

不能存在任何形式的循环语句   

不能存在过多的条件判断语句

函数体不能过于庞大

不能对函数进行取址操作

函数内联声明必须在调用语句之前

编译器对于内联函数的限制并不是绝对的,内联函数相对于普通函数的优势只是省去了函数调用时压栈,跳转和返回的开销。

因此,当函数体的执行开销远大于压栈,跳转和返回所用的开销时,那么内联将无意义。

结论:

1)内联函数在编译时直接将函数体插入函数调用的地方

2inline只是一种请求,编译器不一定允许这种请求

3)内联函数省去了普通函数调用时压栈,跳转和返回的开销

 

 

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;inline void fun(){	cout<< "Hello World!" <

带参数的宏

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;//带参数的宏.谨慎带有++ --的参数#define FUN(a,b) ((a) < (b)? (a):(b))inline int fun(int a,int b){	return a < b ? a:b;}int main(){	int var1  = 1;	int var2  = 3;	int a = FUN(++var1,var2++);	cout << a <

函数默认值:

默认参数要么全部都有,要么只在右边

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;int fun(int a,int b  =4){	cout << a << " " << b << endl;}int main(){	fun(1);	return 0;}chunli@Linux:~/c++$ g++ main.cpp  && ./a.out 1 4

如果默认参数在前面,后面也有参数但是没有默认参数,编译报错

默认参数应该在函数的右边

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;int fun(int a  =1,int b){	cout << a << " " << b << endl;}int main(){	fun(1,2);	return 0;}chunli@Linux:~/c++$ g++ main.cpp  && ./a.out main.cpp: In function ‘int fun(int, int)’:main.cpp:4:5: error: default argument missing for parameter 2 of ‘int fun(int, int)’ int fun(int a  =1,int b)     ^

函数占位参数

调用时,必须写够参数

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;int fun(int a ,int b,int){	cout <
<< " "; cout <
<< endl;}int main(){ fun(1,2,4); return 0;}chunli@Linux:~/c++$ g++ main.cpp  && ./a.out 1 2

默认参数 与 占位符在一起

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;//默认参数 与 占位符在一起void fun(int a ,int b,int = 0){	cout <
<< " "; cout <
<< endl;}int main(){ fun(3,2); fun(1,2,4); return 0;}chunli@Linux:~/c++$ g++ -Wall  -g main.cpp  && ./a.out 3 21 2

函数重载:【面试重点】

函数名必须一致

函数返回值类型必须一致

函数的实参类型不一致

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;int  fun(int a){	cout <
<< "\n"; return 1;}int  fun(int *p){ cout << *p << "\n"; return 2;}int  fun(int a ,int b){ cout <
<< " "; cout <
<< endl; return 3;}int main(){ fun(1); fun(3,2); int a = 40; fun(&a); return 0;}chunli@Linux:~/c++$ g++ -Wall  -g main.cpp  && ./a.out 13 240

当函数重载遇到默认参数,C++编译器不允许通过,编译失败

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;int  fun(int a ,int b){	cout <
<< " "; cout <
<< endl; return 1;}int  fun(int a ,int b,int c = 0){ cout <
<< " "; cout <
<< " "; cout <
<< endl; return 2;}int main(){ fun(3,2); return 0;}chunli@Linux:~/c++$ g++ -Wall  -g main.cpp  && ./a.out main.cpp: In function ‘int main()’:main.cpp:21:9: error: call of overloaded ‘fun(int, int)’ is ambiguous  fun(3,2);         ^

当存在二义性的重载函数,你不去调用,编译器就不会报错:

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;int  fun(int a ){	cout <
<< endl; return 1;}int  fun(int a ,int b){ cout <
<< " "; cout <
<< endl; return 1;}int  fun(int a ,int b,int c = 0){ cout <
<< " "; cout <
<< " "; cout <
<< endl; return 2;}int main(){ fun(3); return 0;}chunli@Linux:~/c++$ g++ -Wall  -g main.cpp  && ./a.out 3

函数指针的申明:三种方式:

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;//申明一个函数的数据类型typedef void (fun1) (int a,int b) ;//自定义一个数据类型//申明一个函数的数据类型typedef void (*fun2) (int a,int b) ;//申明了一个指针的数据类型//定义一个函数指针的变量void (*fun3)(int a,int b);int main(){	fun1 *p1 = NULL;	//定义一个函数指针,指向函数的入口地址	fun2  p2 = NULL;	//定义一个函数指针,指向函数的入口地址	return 0;}chunli@Linux:~/c++$ g++  -g main.cpp  && ./a.out

当函数重载与函数指针在一起

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;void fun(int a,int b){	cout << a << endl;	cout << b << endl;}void fun(int a){	cout << a << endl;}int main(){	typedef void (*p_fun) (int a,int b) ;	//申明了一个指针的数据类型	p_fun p = NULL;				//定义一个函数指针,指向函数的入口地址	p = fun;	p(1,3);	//p(3);	//会报错	return 0;}chunli@Linux:~/c++$ g++  -g main.cpp  && ./a.out 13

========= C++ 对C 的扩展 结束 =============

类的初步

类的初步:

类是抽象的,并没有内存空间

对象是具体的

计算圆的面积:

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;class Mycricle{public :	double m_r;	double m_s;public :	double set_r(double r)	{		m_r = r;	}	double get_r()	{		return m_r;	}	double get_s()	{		m_s = 3.14 * m_r *m_r;		return m_s;	}	};int main()	{	Mycricle c1 ,c2;	c1.set_r(10);	cout << c1.get_s() << endl;	c2.set_r(1);	cout << c2.get_s() << endl;	return 0;}chunli@Linux:~/c++$ g++  -g main.cpp  && ./a.out 3143.14

【封装的含义1】

类的威力,用类当函数的参数:

比原来的结构体功能强大很多!

1,类指针

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;class Mycricle{public :	double m_r;	double m_s;public :	void set_r(double r)	{		m_r = r;	}	double get_r()	{		return m_r;	}	double get_s()	{		m_s = 3.14 * m_r *m_r;		return m_s;	}	};void fun(Mycricle *p){	cout << "r="<
get_r() ; cout << " s="<
get_s() << endl;}int main() { Mycricle c1 ,c2; c1.set_r(10); fun(&c1); c2.set_r(1); fun(&c2); return 0;}chunli@Linux:~/c++$ g++ -Wall -g main.cpp  && ./a.out r=10 s=314r=1 s=3.14chunli@Linux:~/c++$

【封装的含义1】

类的威力,用类当函数的参数:

比原来的结构体功能强大很多!

1,类引用

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;class Mycricle{public :	double m_r;	double m_s;public :	void set_r(double r)	{		m_r = r;	}	double get_r()	{		return m_r;	}	double get_s()	{		m_s = 3.14 * m_r *m_r;		return m_s;	}	};void fun(Mycricle &p){	cout << "r="<

类的控制:

public 修饰的成员变量和函数,可以在类的内部和类的外部访问

private 修饰的成员变量和函数,只能可以在类的内部访问,不能在类的外部访问

private 修饰的成员变量和函数,只能可以在类的内部访问,不能在类的外部访问

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;class Mycricle{private :	double m_r;	double m_s;public :	void set_r(double r)	{		m_r = r;	}	double get_r()	{		return m_r;	}	double get_s()	{		m_s = 3.14 * m_r *m_r;		return m_s;	}};void fun(Mycricle &p){	cout << "r="<

默认属性就是私有属性

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;class Mycricle{	int age;//默认清空下,这是一个私有属性};int main()	{	Mycricle c;	c.age = 10;	return 0;}chunli@Linux:~/c++$ g++ -Wall -g main.cpp  && ./a.out main.cpp: In function ‘int main()’:main.cpp:6:6: error: ‘int Mycricle::age’ is private  int age;//默认清空下,这是一个私有属性      ^

在c++中结构体的默认属性的public

chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;struct test{	int age;//默认清空下,是public属性};int main()	{	test t1;	t1.age = 10;	return 0;}chunli@Linux:~/c++$ cat main.cpp #include "iostream"	using namespace std;struct test{	int age;//默认清空下,是public属性};int main()	{	test t1;	t1.age = 10;	cout << t1.age << endl;	return 0;}chunli@Linux:~/c++$ g++ -Wall -g main.cpp  && ./a.out 10

类的申明与实现,分开:

1主函数

chunli@Linux:~/c++$ cat main.cpp #include "teacher.h"	#include "iostream"	using namespace std;int main()	{	teacher t1;	t1.set_age(36);	cout<< (t1.get_age()) << "\n";	return 0;}

2类的声明

chunli@Linux:~/c++$ cat teacher.h #pragma once#ifndef __TEACHER_H_#define __TEACHER_H_class teacher{private:	int age;		char name[32];public:	void set_age(int a);	int  get_age();};#endif

3,类的实现

chunli@Linux:~/c++$ cat teacher.cpp #include "teacher.h"void teacher::set_age(int a){	age = a;}int teacher::get_age(){	return age;}

编译运行

chunli@Linux:~/c++$ g++ -g  main.cpp  teacher.cpp  && ./a.out 36

转变到面向对象转变过程

chunli@Linux:~/c++$ cat mycube.cpp #include 
using namespace std;class Cube{public: void set_abc(int a=0,int b=0,int c=0) { m_a = a; m_b = b; m_c = c; } int get_v() { m_v = m_a * m_b * m_c; return m_v;  } int get_s() { m_s = 2*((m_a * m_b)+(m_a * m_c)+(m_b * m_c)); return m_s; }private: int m_a; int m_b; int m_c; int m_v; int m_s;};int main(){ Cube v1; v1.set_abc(1,1,1); cout << "体积= "<
<< endl; cout << "面积= "<
<< endl; return 0;}chunli@Linux:~/c++$ g++ -Wall -g mycube.cpp  && ./a.out 体积= 1面积= 6

加料啦!

比较两个立方体的是否一样

1,用外部函数来比较

chunli@Linux:~/c++$ cat mycube.cpp #include 
using namespace std;class Cube{public: void set_abc(int a=0,int b=0,int c=0) { m_a = a; m_b = b; m_c = c; } int get_v() { m_v = m_a * m_b * m_c; return m_v;  } int get_s() { m_s = 2*((m_a * m_b)+(m_a * m_c)+(m_b * m_c)); return m_s; } int get_a(){return m_a;} int get_b(){return m_b;} int get_c(){return m_c;}private: int m_a; int m_b; int m_c; int m_v; int m_s;};int main(){ Cube v1; v1.set_abc(1,1,1); Cube v2; 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 << "not equal \n"; } return 0;}chunli@Linux:~/c++$ g++ -Wall -g mycube.cpp  && ./a.out not equal

用面向对象的方式 实现立方体的比较

chunli@Linux:~/c++$ cat mycube.cpp #include 
using namespace std;class Cube{public: void set_abc(int a=0,int b=0,int c=0) { m_a = a; m_b = b; m_c = c; } int get_v() { m_v = m_a * m_b * m_c; return m_v;  } int get_s() { m_s = 2*((m_a * m_b)+(m_a * m_c)+(m_b * m_c)); return m_s; } int get_a(){return m_a;} int get_b(){return m_b;} int get_c(){return m_c;} int judge(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()) { return 1; } else { return 0; } }private: int m_a; int m_b; int m_c; int m_v; int m_s;};int main(){ Cube v1; v1.set_abc(1,1,1); Cube v2; v2.set_abc(1,1,1); if(v1.judge(v2) == 1){cout << "equal \n";} else{ cout << "not equal \n"; } return 0;}chunli@Linux:~/c++$ g++ -Wall -g mycube.cpp  && ./a.out equal

用面向对象的思路求【点】是否在【圆】内

涉及到两个类,一个是点,一个是圆

源代码:

chunli@Linux:~/c++$ cat mycube.cpp #include 
using namespace std;//class MyPoint; 这是类的前置申明class MyPoint{public: int get_x(){return x1;} int get_y(){return y1;} void setPoint(int _x1,int _y1) { x1 = _x1; y1 = _y1; }private: int x1; int y1;};class advCircle{public: void setCircle(int _r,int _x0,int  _y0) { r  = _r; x0 = _x0; y0 = _y0; } int judge(MyPoint &p) { int l = (p.get_x() - x0) * (p.get_y() -y0); if(r * r > l) { return 1; } else { return 0; } }private: int r; int x0; int y0;};int main(){ advCircle c1; c1.setCircle(2,3,3); MyPoint p1; p1.setPoint(7,7); if(c1.judge(p1) ==1 ) { cout << "在圆内\n"; } else { cout << "在圆外\n"; } return 0;}chunli@Linux:~/c++$ g++ -Wall -g mycube.cpp  && ./a.out 在圆外

把类的申明与实现分开写:

有这么5个文件:

chunli@Linux:~/c++$ ll total 20K-rw-rw-r-- 1 chunli chunli 347 Jun 28 16:46 advCircle.cpp-rw-rw-r-- 1 chunli chunli 253 Jun 28 16:49 advCircle.h-rw-rw-r-- 1 chunli chunli 263 Jun 28 16:50 main.cpp-rw-rw-r-- 1 chunli chunli 172 Jun 28 16:39 MyPoint.cpp-rw-rw-r-- 1 chunli chunli 215 Jun 28 16:42 MyPoint.h

文件1:

chunli@Linux:~/c++$ cat advCircle.h #pragma once#include "MyPoint.h"#ifndef __ADVCIRCLE_H_#define __ADVCIRCLE_H_class advCircle{public:        void setCircle(int _r,int _x0,int  _y0);        int judge(MyPoint &p);private:        int r;        int x0;        int y0;};#endif

文件2:

chunli@Linux:~/c++$ cat advCircle.cpp #include "advCircle.h"void advCircle::setCircle(int _r,int _x0,int  _y0){        r  = _r;        x0 = _x0;        y0 = _y0;}int advCircle::judge(MyPoint &p){        int l = (p.get_x() - x0) * (p.get_y() -y0);        if(r * r > l)        {                return 1;        }        else        {                return 0;        }}

文件3:

chunli@Linux:~/c++$ cat MyPoint.h #pragma once#ifndef __MYPOINT_H_#define __MYPOINT_H_class MyPoint{private:        int x1;        int y1;public:        int get_x();        int get_y();        void setPoint(int _x1,int _y1);};#endif

文件4:

chunli@Linux:~/c++$ cat MyPoint.cpp #include "MyPoint.h"int MyPoint::get_x(){return x1;}int MyPoint::get_y(){return y1;}void MyPoint::setPoint(int _x1,int _y1){        x1 = _x1;        y1 = _y1;}

文件5:

chunli@Linux:~/c++$ cat main.cpp #include "MyPoint.h"#include "advCircle.h"#include 
using namespace std;int main(){ advCircle c1; c1.setCircle(2,3,3); MyPoint p1; p1.setPoint(7,7); if(c1.judge(p1) ==1 ) { cout << "在圆内\n";} else { cout << "在圆外\n";} return 0;}

编译运行:

chunli@Linux:~/c++$ g++ -g main.cpp  MyPoint.cpp advCircle.cpp  && ./a.out  在圆外

作业:

第1题:

chunli@Linux:~/c++$ cat main.cpp #include 
using namespace std; class cricle{private: int r; int x; int y;public: int get_x(){return x;} int get_y(){return y;} int get_r(){return r;} void set_rxy() { cout << "请输入圆的半径,x,y坐标   "; cout << "如 1 4 2 代表半径为1,横坐标为4纵坐标为2\n"; cin >> r >> x >> y; } int judge(cricle c) { int l = (c.get_x() - x )* (c.get_x() - x )   +  (c.get_y() - y) * (c.get_y() - y); int d = (r + c.get_r()) * (r + c.get_r()); if(d  ==  l  ) { return 0; } else if( d  >  l  ) { return 1; } else { return -1; } }};int main(){ cricle c1; c1.set_rxy(); cricle c2; c2.set_rxy(); int ret = c1.judge(c2); if(ret == 0) { cout << "两圆相切\n"; } else if(ret == -1) { cout << "两圆相离\n"; } else { cout << "两圆相交\n"; } return 0;}chunli@Linux:~/c++$ 编译运行:chunli@Linux:~/c++$ g++ -g -Wall main.cpp   && ./a.out 请输入圆的半径,x,y坐标   如 1 4 2 代表半径为1,横坐标为4纵坐标为21 2 2请输入圆的半径,x,y坐标   如 1 4 2 代表半径为1,横坐标为4纵坐标为21 3 2两圆相交chunli@Linux:~/c++$ g++ -g -Wall main.cpp   && ./a.out 请输入圆的半径,x,y坐标   如 1 4 2 代表半径为1,横坐标为4纵坐标为21 2 2 请输入圆的半径,x,y坐标   如 1 4 2 代表半径为1,横坐标为4纵坐标为21 4 2两圆相切chunli@Linux:~/c++$ g++ -g -Wall main.cpp   && ./a.out 请输入圆的半径,x,y坐标   如 1 4 2 代表半径为1,横坐标为4纵坐标为21 2 2 请输入圆的半径,x,y坐标   如 1 4 2 代表半径为1,横坐标为4纵坐标为21 5 2两圆相离

第2题:

chunli@Linux:~/c++$ cat main.cpp #include 
using namespace std; class Rectangle{private: int x1; int y1; int x2; int y2; int s;public: void set_xy(int _x1,int _y1,int _x2,int _y2) { x1 = _x1; y1 = _y1; x2 = _x2; y2 = _y2; } int get_s() { s = (x2 - x1) * (y2 -y1); return s; }};int main(){ Rectangle r1; r1.set_xy(0,0,4,4); cout << r1.get_s() << endl; return 0;}chunli@Linux:~/c++$ g++ -g -Wall main.cpp   && ./a.out 16

第3题:

chunli@Linux:~/c++$ cat main.cpp #include 
using namespace std;class Tree{private: int n;public: void grow(int _age) { n = _age; } int age() { return n; }};int main(){ Tree t1; t1.grow(99); cout << t1.age() << endl; return 0;}chunli@Linux:~/c++$ g++ -g -Wall main.cpp   && ./a.out 99