C++核心编程Day02

1.内联函数

1.1 内联函数基本概念
	在c++中,预定义宏的概念是用内联函数来实现的,而内联函数本身也是一个真
正的函数。内联函数具有普通函数的所有行为。唯一不同之处在于内联函数会在适当
的地方像预定义宏一样展开,所以不需要函数调用的开销。因此应该不使用宏,使用
内联函数。
	在普通函数(非成员函数)函数前面加上inline关键字使之成为内联函数。但是必须注
意必须配合函数体的定义结合在一起,否则编译器将它作为普通函数来对待。
	内联函数的确占用空间,但是内联函数相对于普通函数的优势只是省去了函数调用
时候的压栈,跳转,返回的开销。我们可以理解为内联函数是以空间换时间。

1.2 类内部的内联函数
	为了定义内联函数,通常必须在函数定义前面放一个inline关键字。但是在类内部
定义内联函数时并不是必须的。任何在类内部定义的函数自动成为内联函数。

1.3 内联函数和编译器
	对于任何类型的函数,编译器会将函数类型(包括函数名字,参数类型,返回值类型)
放入到符号表中。同样,当编译器看到内联函数,并且对内联函数体进行分析没有发现
错误时,也会将内联函数放入符号表。
	当调用一个内联函数的时候,编译器首先确保传入参数类型是正确匹配的,或者如果
类型不能完全匹配,但是可以将其转换为正确类型,并且返回值在目标表达式里匹配正
确类型,或者可以转换为目标类型,内联函数就会直接替换函数调用,这就消除了函数
调用的开销。假如内联函数是成员函数,对象this指针也会被放入合适位置。
注:
	c++内联编译会有一些限制,以下情况编译器可能考虑不会将函数进行内联编译:
	1.不能存在任何形式的循环语句
	2.不能存在过多的条件判断语句
	3.函数体不能过于庞大
	4.不能对函数进行取址操作
	
	内联仅仅只是给编译器一个建议,编译器不一定会接受这种建议,如果你没有将函
数声明为内联函数,那么编译器也可能将此函数做内联编译。一个好的编译器将会内
联小的、简单的函数。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#define ADD(x,y) ((x)+(y))
//内联函数
inline int Add(int x, int y)
{
	return x + y;
}

void test01()
{
	int a = 10;
	int b = 20;
	cout << ADD(a, b) << endl;
	cout << Add(a, b) << endl;
}

#define MyTEST(x,y) ((x)<(y)?(x):(y))
inline int func2(int x,int y)
{
	return x < y ? x : y;
}

//注:以下操作就是内联函数和宏函数的区别
void test02()
{
	int a = 1;
	int b = 3;
	//执行操作是 MyTEST(a,b) ((++a)<(b)?(++a):(b)) = 3
	//cout << MyTEST(++a, b) << endl;
	cout << func2(a, b) << endl;
}

int main()
{
	//test01();
	test02();

	system("pause");
	return 0;
}

2.函数的参数

2.1 函数的默认参数
	c++在声明函数原型的时可为一个或者多个参数指定默认(缺省)的参数值,当函数
调用的时候如果没有指定这个值,编译器会自动用默认值代替,并且,在设定了默认
参数之后,这个参数之后的参数都要提前设定默认值。
2.2 函数的占位参数
	c++在声明函数时,可以设置占位参数。占位参数只有参数类型声明,而没有参数
名声明。一般情况下,在函数体内部无法使用占位参数。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

int test01(int a,int b = 10)
{
	return a + b;
}

//注意1:函数的默认参数后面的参数必须都是默认参数
int test02(int a, int b = 10,int c = 0,int d = 10)
{
	return a + b + c + d;
}
//注意2:函数的声明和实现不能同时有默认参数,即要么声明有默认参数,要不实现有默认参数
void test03(int a, int b );
void test03(int a, int b = 0)
{
	cout << "test03调用" << endl;
}

//函数的占位参数,在运算符重载的时候区分前加加和后加加的时候使用
void test04(int a, int = 10)
{
	cout << "test04()的调用" << endl;
}

int main()
{
	//cout << test01(5) << endl;
	//cout << test01(5,5) << endl;
	//test03(10);
	test04(10);
	system("pause");
	return 0;
}

3.函数重载

3.1 函数重载基本语法
	实现函数重载的条件:
	1.同一个作用域
	2.参数个数不同
	3.参数类型不同
	4.参数顺序不同
注: 函数重载和默认参数一起使用,需要额外注意二义性问题的产生。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

//函数重载的原理
//在汇编阶段,起别名
//例如:int add(int a, int b)别名就是 __addii
//		int add(int a, double b)别名就是 __addid
//		int add(double a,int b)别名就是__adddi
//		int add()别名就是__addv

//函数重载的三种形式(在同一作用域下)
//1.按照函数的参数类型
//2.按照函数的参数个数
//3.按照函数的参数顺序
int add(int a, int b)
{
	return a + b;
}

int add(int a, double b)
{
	return a + b;
}

int add(double a,double b)
{
	return a + b;
}

int add(double a,int b)
{
	return a + b;
}

//函数重载和默认参数进行配合使用的时候要注意二义性
void myFunc(int a,int b = 0)
{
	cout << "myFunc(int a,int b = 0)的调用" << endl;
}

void myFunc(int a)
{
	cout << "myFunc(int a)的调用" << endl;
}

void myFunc()
{
	cout << "myFunc()的调用" << endl;
}

int main()
{
	int a = 10;
	double b = 20;

	cout << add(a, a) << endl;
	cout << add(a, b) << endl;
	cout << add(b, b) << endl;
	cout << add(b, a) << endl;

	//myFunc(a);//调用是错误的,是因为函数重载后,传入一个a,函数不知道该调用myFunc(int a),还是该调用"myFunc(int a,int b = 0)
	myFunc(a,a);


	system("pause");
	return 0;
}
3.2 函数重载实现原理
	编译器为了实现函数重载,用不同的参数类型来修饰不同的函数名,比如void func(); 
编译器可能会将函数名修饰成_func,当编译器碰到void func(int x),编译器可能将函数
名修饰为func_int,当编译器碰到void func(int x,char c),编译器可能会将函数名修饰为
_func_int_char。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

//函数重载的原理
//在汇编阶段,起别名
//例如:int add(int a, int b)别名就是 __addii
//		int add(int a, double b)别名就是 __addid
//		int add(double a,int b)别名就是__adddi
//		int add()别名就是__addv

//函数重载的三种形式(在同一作用域下)
//1.按照函数的参数类型
//2.按照函数的参数个数
//3.按照函数的参数顺序
int add(int a, int b)
{
	return a + b;
}

int add(int a, double b)
{
	return a + b;
}

int add(double a,double b)
{
	return a + b;
}

int add(double a,int b)
{
	return a + b;
}

//函数重载和默认参数进行配合使用的时候要注意二义性
void myFunc(int a,int b = 0)
{
	cout << "myFunc(int a,int b = 0)的调用" << endl;
}

void myFunc(int a)
{
	cout << "myFunc(int a)的调用" << endl;
}

void myFunc()
{
	cout << "myFunc()的调用" << endl;
}

int main()
{
	int a = 10;
	double b = 20;

	cout << add(a, a) << endl;
	cout << add(a, b) << endl;
	cout << add(b, b) << endl;
	cout << add(b, a) << endl;

	//myFunc(a);//调用是错误的,是因为函数重载后,传入一个a,函数不知道该调用myFunc(int a),还是该调用"myFunc(int a,int b = 0)
	myFunc(a,a);


	system("pause");
	return 0;
}
3.3 在C++中调用C语言程序注意事项
	在C++中要是调用C语言的函数的话,一般都不能正常编译通过,之所以会出
现这种问题,就是因为编译器在函数编译之后,会将函数名字改为上述的形式,在C++
和C中编写的函数函数名是不同的,因此当编译器在C++的环境下使用,C语言编写的函
数的话,编译器就无法正确识别所需的函数,因此就需要一些特殊手段。
#define _crt_secure_no_warnings
#include<iostream>
#include<string>
using namespace std;

//c++的函数在汇编的时候,会给函数起别名,例如调用void func()函数,就会起名为__z4funcv,
//而c语言在汇编后,给函数的名字会只有一个下划线,即_func,因此此时使用c++调用c语言的函数的时候就会报错


//例如,在一般情况下,我们定义了一个c语言的头文件,然后进行声明
//在c++中调用的时候,应该在c语言的头文件(.h文件中)中,以以下格式进行书写

/*
#ifdef __cplusplus
extern "c"
{
#endif
	void func();//这是用c写的代码文件,就是告诉编译器以c的方式进行查找该函数,并起到声明的作业

#ifdef __cplusplus
}
#endif
*/
int main()
{

	system("pause");
	return 0;
}

4. 类和对象

4.1  C和C++中struct区别
	1.c语言struct只有变量	
	2.c++语言struct 既有变量,也有函数
	
	 struct和class的区别:
		class默认访问权限为private,struct默认访问权限为public.
		
4.2 类的封装
	1.把变量(属性)和函数(操作)合成一个整体,封装在一个类中
	2. 对变量和函数进行访问控制
	访问权限:
		1.在类的内部(作用域范围内),没有访问权限之分,所有成员可以相互访问
		2.在类的外部(作用域范围外),访问权限才有意义:public,private,protected
		在类的外部,只有public修饰的成员才能被访问,在没有涉及继承与派生时,
		private和protected是同等级的,外部不允许访问。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

//类的封装
//将属性和方法封装到类中

//三种权限
//1.public:类外和类内都可以访问
//2.protected:类外不可以访问,类内可以访问(子类的类内可以访问父类的保护成员)
//3.private:类外不可以访问,类内可以访问

class Maker//类
{
public:
	void set(string name,int id)//成员函数
	{
		this->id = id;
		this->name = name;
	}
	void printMaker()
	{
		cout << "姓名:" << this->name << "\n序号:" << this->id<<endl;
	}
private:
	int id;//成员变量
	string name;
};

void test01()
{
	Maker m;//m是对象
	m.set("张三", 1);
	m.printMaker();
}

int main()
{
	test01();
	system("pause");
	return 0;
}
4.3将成员变量设置为private的作用:
1.可赋予客户端访问数据的一致性。
	如果成员变量不是public,客户端唯一能够访问对象的方法就是通过成员函数。
如果类中所有public权限的成员都是函数,客户在访问类成员时只会默认访问函数,
不需要考虑访问的成员需不需要添加()。

2.可细微划分访问控制。
	使用成员函数可使得我们对变量的控制处理更加精细。如果我们让所有的成员变
量为public,每个人都可以读写它。如果我们设置为private,我们可以实现“不准访
问”、“只读访问”、“读写访问”,甚至你可以写出“只写访问”。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

class Maker//类
{
public:
	void initMaker()//成员函数
	{
		this->name = " ";
		this->age = 0;
	}

	void scanfName(string name)//写姓名
	{
		this->name = name;
	}

	void printName()//读姓名
	{
		cout << "姓名:" << this->name << endl;
	}

	void scanfAge(int age)//写年龄
	{
		if (age >= 0 && age <= 100)
		{
			this->age = age;
			return;
		}
	}
	void printAge()//读年龄
	{
		cout << "年龄:" << this->age << endl;
	}
private:

	int age;
	string name;
};

void test01()
{
	Maker m;
	m.initMaker();
	m.printName();
	m.printAge();

	m.scanfName("张三");
	m.scanfAge(18);
	m.printName();
	m.printAge();
}


int main()
{
	test01();
	system("pause");
	return 0;
}

5.案例

5.1 设计立方体类(Cube),求出立方体的面积( 2*a*b + 2*a*c + 2*b*c )和体积( a * b * c),
分别用全局函数和成员函数判断两个立方体是否相等。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;


class Cude
{
public:
	void initCube()
	{
		this->longth = 0;
		this->length = 0;
		this->height = 0;
	}

	void setLongth(int longth)
	{
		this->longth = longth;
	}

	void setLength(int length)
	{
		this->length = length;
	}

	void setHeight(int height)
	{
		this->height = height;
	}

	int squareCube()
	{
		return 2 * (this->height + this->length + this->longth);
	}

	int volumeCube()
	{
		return this->height * this->length * this->longth;
	}

	int comPareCube(Cude c1)
	{
		if (this->longth == c1.longth && this->height == c1.height && this->length == c1.length)
			return 1;
		else
			return 0;
	}
private:
	int longth;
	int length;
	int height;

};

int compareSquareCube(Cude c1,Cude c2)
{
	if (c1.squareCube() == c2.squareCube())
		return 1;
	return 0;
}

int comparevolumeCube(Cude c1, Cude c2)
{
	if (c1.volumeCube() == c2.volumeCube())
		return 1;
	return 0;
}

void test01()
{
	Cude c1;
	Cude c2;
	c1.initCube();
	c1.setHeight(30);
	c1.setLength(20);
	c1.setLongth(10);
	
	c2.initCube();
	c2.setLongth(10);
	c2.setLength(20);
	c2.setHeight(30);

	//成员函数
	if (c1.comPareCube(c2))
		cout << "相等!" << endl;
	else
		cout << "不相等!" << endl;

	//全局函数
	if (compareSquareCube(c1, c2))
		cout << "面积相等!" << endl;
	else
		cout << "面积不相等!" << endl;

	if (comparevolumeCube(c1, c2))
		cout << "体积相等!" << endl;
	else
		cout << "体积不相等!" << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}
5.2 点和圆的关系
设计一个圆形类(AdvCircle),和一个点类(Point),计算点和圆的关系。
假如圆心坐标为x0, y0, 半径为r,点的坐标为x1, y1:
	1)点在圆上:(x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) == r*r
	2)点在圆内:(x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) < r*r
	3)点在圆外:(x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) > r*r
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

class Point
{
public:
	void initPoint()
	{
		this->p_x = 0;
		this->p_y = 0;
	}

	void setX(int x)
	{
		p_x = x;
	}

	void setY(int y)
	{
		p_y = y;
	}

	int getX()
	{
		return this->p_x;
	}
	int getY()
	{
		return this->p_y;
	}

private:
	int p_x;
	int p_y;
};

class Circle
{
public:
	void initCircle()
	{
		c_point.setX(0);
		c_point.setY(0);
		c_r = 0;
	}
	void setCircle(int x,int y,int r)
	{
		c_point.setX(x);
		c_point.setY(y);
		c_r = r;
	}
	
	int compareCirPoi(Point p1)
	{
		if (((this->c_point.getX() - p1.getX()) * (this->c_point.getX() - p1.getX()) + (this->c_point.getY() - p1.getY()) * (this->c_point.getY() - p1.getY())) == (this->c_r * this->c_r))
			return 0;

		if (((this->c_point.getX() - p1.getX()) * (this->c_point.getX() - p1.getX()) + (this->c_point.getY() - p1.getY()) * (this->c_point.getY() - p1.getY())) > (this->c_r * this->c_r))
			return 1;
		else
			return -1;
	}

private:
	Point c_point;
	int c_r;
};

void test01()
{
	Point p1;
	Circle c1;
	p1.initPoint();
	p1.setX(10);
	p1.setY(10);

	c1.initCircle();
	c1.setCircle(10, 20, 5);
	if (c1.compareCirPoi(p1) == 0)
		cout << "在圆上!" << endl;
	else if (c1.compareCirPoi(p1) == 1)
		cout << "在圆外!" << endl;
	else
		cout << "在圆内!" << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值