C++学习笔记(2):内联函数、默认参数、函数重载、函数指针、类和对象、类的封装

一、内联函数
内联函数的特点:
1)内联函数声明时inline关键字必须和函数定义结合在一起,否则编译器会直接忽略内联请求。
2)C++编译器直接将函数体插入在函数调用的地方
3)内联函数没有普通函数调用时额外的开销(压栈,跳转,返回)
4)内联函数是一种特殊的函数,具有普通函数的特征(参数检查,返回类型等)
5)内联函数由编译器处理,直接将编译后的函数体插入调用的地方
宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程
6)C++中的内联编译的限制:
不能存在任何形式的循环语句、不能存在过多的条件判断语句、函数体不能过于庞大、不能对函数进行取址操作、函数内联声明必须在调用语句之前
7)编译器对于内联函数的限制并不是绝对的,内联函数相当于普通函数的优势只是省去了函数调用时压栈,跳转和返回的开销,因此,当函数体的执行开销远大于压栈,跳转和返回所用的开销时,那么内联将毫无意义

#include <iostream>
#define MAX(a,b)   ((a)>(b)?(a):(b))  //宏函数可以解决压栈和出栈的开销,但是解决不了参数传递的弊端
using namespace std;

int max(int a, int b){
	return (a>b)?a:b;
}

void printAB(int a, int b){
	cout << "a = "<< a <<" ,b = " << b << endl;
}

inline void printAB_2(int a, int b){
	cout << "a = "<< a <<" ,b = " << b << endl;
}

int main(void){
	int a = 10;
	int b = 20;
	int c = 0;
	c = MAX(a, b);
	cout << "c = "<< c << endl;
	for(int i= 0; i<1000; i++){
		a++;
		b++;
		printAB_2(a, b);//这行函数相当于
		// {
		//   cout << "a = "<< a <<" ,b = " << b << endl;
		//  }
		//即在原位置直接将代码展开,这个展开并不是预处理器展开的
		//而是编译器展开的,并且可以校验传参数的正确性
		//只不过省略了压栈和出栈的过程
	}
#if 0
	for(int i= 0; i<1000; i++){
		a++;
		b++;
		printAB(a, b);//会经历1000次压栈和出栈
	}	
#endif
	return 0;
}

二、默认参数和占位参数

#include <iostream>
using namespace std;

void func(int a = 999){//默认参数
	cout << "a  = " << a << endl;
}


int get_volume(int len , int wight, int hight=10){  //多个参数必须从右向左有默认值
	return len * wight * hight; 
}

void func(int a, int){ //占位参数  亚元
	cout << "a = "<< a <<endl;

}

int main(void){
	int value = 10;
	func(10);
	cout << "volume = " << get_volume(1,1)<< endl;
	func(value, 10);

	return 0;	
}

三、函数重载
重载规则:
1、函数名相同
2、参数个数不同,参数的类型不同,参数顺序不同,均可构成重载
3、返回值类型不同则可以构成重载
重载的底层实现:倾扎(name mangling)技术

#include <iostream>
using namespace std;

//函数的返回值,函数的形参列表(参数个数,参数类型,参数顺序)
//函数重载 函数名相同,参数列表不同
//返回值并不是构成函数重载的条件
int func(int a, char b){
	cout << "func1" << endl; 
	return 0;
}

//如果要是函数重载的话,不要写默认参数,为了避免调用出现函数冲突
int func(int a, int b){
	cout << "func2" << endl;
	return 1;
}

int func(int a, char* b){
	cout << "func3" << endl;
	return 1;
}

void print(int a){
	cout << "print1" << endl;
	cout << a <<endl; 
	return;
}

void print(double a){
	cout <<"print2"<<endl;
	cout<< a << endl;
}

void print(char a){
	cout <<"print3"<<endl;
	cout <<"a = "<< a <<endl;
}

int main(void){
	func(1 ,"abd");//func3
	print(1);
	print(2.0);
	print('a');
	//1 如果能够严格匹配调用完全匹配的
	//2 如果不能严格匹配,调用隐式转换
	//3 都匹配不到,调用失败
	return 0;
}

四、函数重载和函数指针

#include <iostream>
using namespace std;

int func(int a, int b){
	cout << "func1" << endl;
	return 0;
}

int func(int a, int b, int c){
	cout << "func2" << endl;
	return 0;
}

//1.定义一种函数类型(函数指针)
typedef int(MY_FUNC)(int,  int);

//2.定义一个指向这种函数类型的指针类型
typedef  int(*MY_FUNC_P)(int, int);

int main(void){
	//1.
	MY_FUNC *fp = NULL;
	fp = func;
	fp(10,20);//两种方式调用func
	(*fp)(10,20);

	//2.好理解
	MY_FUNC_P fp1 = NULL;
	fp1 = func;
	fp1(10,20);

	//3.比较常用的方式
	int(*fp3)(int, int) = NULL;
	fp3 = func;
	fp3(10,20);
	func(10,20);
	func(10,20,30);

	fp3 = func;//fp3->func(int, int)
	
	//实际上在给函数指针赋值的时候,是会发生函数的重载匹配的
	//在调用函数指针的时候,所调用的函数就已经固定了
	int(*fp4)(int,int,int) = NULL;
	fp4 = func;// fp4 --> func(int, int,int)
	fp4(10,20,40);
	fp3(10,30);//func(int, int)
	//fp3(10,20,30);  无法调用func(int, int,int)  因为指针只指向func1
	return 0;
}

五、类和对象

#include <iostream>
using namespace std;

struct Hero{
	char name[64];
	int sex;
};

class AdvHero{
public://访问控制权限
	char name[64];
	int sex;
	
	void printHero(){
		cout <<"AdnHero-----"<<endl;
		cout << "name = " << name <<endl;
		cout << "sex = " << sex << endl;	
	}
};

class Animal{
	//{}以内称为类的内部,以外叫外部
public:
	//在public下面定义的成员变量和函数 是能够在类的内部和外部都可以访问的
	char kind[64];
	char color[64];

	void printAnimal(){
		cout << "kind = " << kind << endl;
		cout << "color = " << color << endl;
	}

	void run(){
		cout << kind << " 开始跑步了" <<endl;
	}

	void write(){
		cout << kind << " 开始写字了" << endl;	
	}
private:
	//在private下面定义的成员变量和方法只能在类的内部访问
	int age;
};

void printHero(struct Hero &h){
	cout << "Hero-----"<<endl;
	cout << "name = "<< h.name << endl;
	cout << "sex = " << h.sex <<endl;
}

int main(void){
	Hero h;//变量类型 变量
	strcpy(h.name , "gailun");
	h.sex = 1;
	printHero(h);
	AdvHero Adh;//类名  对象
	strcpy(Adh.name , "uzi");
	Adh.sex = 1;
	Adh.printHero();

	cout << "--------------"<<endl;

	Animal dog;
	strcpy(dog.kind, "dog");
	strcpy(dog.color, "yellow");

	Animal sheep;
	strcpy(sheep.kind, "sheep");
	strcpy(sheep.color, "white ");
	dog.run();
	sheep.write();

	return 0;
}

六、类的封装

#include <iostream>
using namespace std;

//一个结构体,默认的访问权限是public  
struct Date{
	int year;
	int month;
	int day;
	//结构体中也可以写 成员方法
};
//在C++中结构体和类唯一的区别就是默认访问权限不一样	
//结构体实际上就是一个类

void init_data(struct Date &d){
	cout << "year, month, day"<<endl;
	cin >> d.year;
	cin >> d.month;
	cin >> d.day;
}

//打印date接口
void print_date(struct Date &d){
	cout << d.year << "年" << d.month << "月" <<d.day << "日" << endl;	
}

//判断是否是闰年
bool is_leap_year(struct Date &d){
	if( (d.year%4 ==0) && (d.year % 100 != 0) || (d.year %400 == 0) ){
		return true;
	}
	return false;
}

//一个类的内部,默认的控制访问权限是private
class MyDate
{
public:
	//成员方法  成员函数
	void init_date(){
		cout << "year, month, day" << endl;
		cin >> year;
		cin >> month;
		cin >> day;
	}

	void print_date(){
		cout << year << "年" << month << "月" << day << "日"  <<endl;
	}

	bool is_leap_year(){
		if( (year % 4 == 0)&&(year % 100 != 0) || (year % 400 ==0)	){
			return true;
		}
		return false;
	}

	int get_year(){
		return year;
	}

	void set_year(int new_year){
		year = new_year;
	}
protected://保护控制权限。在类的继承中与private有区别,在类中与private中是一模一样的
private:
	//一般类中的变量(成员变量),存放在private区域中
	int year;
	int month;
	int day;
};

int main(void){
#if 0
	Date d1;
	init_data(d1);
	print_date(d1);
	if(is_leap_year(d1)){
		cout << "是闰年" << endl;
	}
	else{
		cout << "不是闰年" << endl;
	}
#endif
	cout << "----------------------------" << endl;

	MyDate md;
	md.init_date();
	md.print_date();
	if( md.is_leap_year() ){
		cout << "Yes" << endl;
	}
	else{
		cout<< "No" <<endl;
	}

	//getter,setter
	cout << md.get_year() << endl;
	md.set_year(2000);
	cout << md.get_year() << endl;
	return 0;
}

七、面向过程和面向对象

#include <iostream>
using namespace std;

//面向对象
class Dog{
public:
	char name[64];

	void eat(char *food){
		cout << name << "吃" << food <<endl;
	}
};

//面向过程
void eat(class Dog &dog, char *food){
	cout << dog.name << "吃" << food << endl; 
}

int main(void){
	Dog dog;
	strcpy(dog.name, "狗");
	eat(dog, "shit");
	dog.eat("shit");
	return 0;
}

八、类和对象的一个小例子
例1:求圆的面积和周长(单文件)

#include <iostream>
using namespace std;

//圆的周长
double getCircleGirth(double r)
{
	return 2 * 3.14 * r;
}

//圆得面积
double getCircleArea(double r)
{
	return 3.14*r*r;	
}

//使用面向对象方法实现上面的业务
//类名一般首字母大写
class Circle
{
public:
	double getR(){
		return m_r;
	}

	void setR( double r){
		m_r = r;
	}

	double getCircleGirth(){	
		return 2 * 3.14 * m_r;
	}

	double getCircleArea(){
		return 3.14*m_r*m_r;	
	}
private:
	double m_r;
};

class Circle2
{
public:
	double getR(){
		return m_r;
	}

	void setR( double r){
		m_r = r;
	}

	double getCircleGirth(){	
		m_girth =  2 * 3.14 * m_r;
		return m_girth;
	}

	double getCircleArea(){
		m_area =  3.14*m_r*m_r;	
		return m_area;
	}

private:
	double m_r;
	double m_girth;
	double m_area;
};

int main(void){
	double r = 10; //圆的半径

	double g = 0;//周长
	double a = 0;//面积

	//面向过程以函数为驱动
	g = getCircleGirth(r);
	a = getCircleArea(r);
	cout << "圆的半径:" << r << endl;
	cout << "圆的周长:" << g << endl;
	cout << "圆的面积:" << a << endl;

	cout << "------------------------------" << endl;
	
	//面向对象以对象为驱动
	Circle c1;
	c1.setR(10.0);
	cout << "圆的半径:" << c1.getR() << endl;
	cout << "圆的周长:" << c1.getCircleGirth() << endl;
	cout << "圆的面积:" << c1.getCircleArea() << endl;

	cout << "------------------------------" << endl;

	Circle2 c2;
	c2.setR(10.0);
	cout << "圆的半径:" << c2.getR() << endl;
	cout << "圆的周长:" << c2.getCircleGirth() << endl;
	cout << "圆的面积:" << c2.getCircleArea() << endl;
	
	return 0;
}

例2:求圆的面积和周长(多文件)
Circle.h:

#pragma once
//头文件只写声明,不写定义
class Circle
{
public:
	//设置半径
	void setR(double r);
	//得到半径
	double getR();
	//得到面积
	double getArea();
	//得到周长
	double getGirth();

private:
	double m_r;
	double m_area;
	double m_grith;
};

Circle.cpp:

#include "Circle.h"

//设置半径
void Circle::setR(double r){
	m_r = r;
}

//得到半径
double Circle::getR(){
	return m_r;
}
//得到面积
double Circle::getArea(){
	m_area = m_r * m_r * 3.14;
	return m_area;
}

//得到周长
double Circle::getGirth(){
	m_grith = 2 * 3.14 * m_r;
	return m_grith;
}

main.cpp:

#include <iostream>
#include "Circle.h"
using namespace std;

int main(void){
	Circle c;
	c.setR(10);
	
	cout << "面积:" << c.getArea() <<endl;
	cout << "周长:" << c.getGirth() <<endl;

	return 0;
}

例3:求点在圆的内部(单文件)

#include <iostream>
using namespace std;

class Point
{
public:
	void setXY(int x, int y){
		m_x = x;
		m_y = y;
	}

	int getX(){
		return m_x;
	}

	int getY(){
		return m_y;
	}

private:
	int m_x;
	int m_y;
};

class Circle
{
public:
	void setXY(int x, int y){
		m_x = x;
		m_y = y;
	}

	void setR(int r){
		m_r = r;
	}

	bool IsInsideCircle( Point &p){
		if( m_r*m_r > (m_x - p.getX())*(m_x - p.getX()) + (m_y - p.getY())*(m_y - p.getY()) ){
			return true;
		}
		else{
			return false;
		}
	}
private:
	int m_x;
	int m_y;
	int m_r;
};

int main(void){
	Point p;
	p.setXY(2,2);
	Circle c;
	c.setXY(0,0);
	c.setR(10);
	if(c.IsInsideCircle(p)){
		cout<< "点 (" << p.getX() << "," << p.getY() << ")在圆内" << endl;
	}
	else{
		cout <<  "不在圆中" << endl;
	}
	
	return 0;
}

例3:求点在圆的内部(多文件)
Point.h:

#pragma once
class Point
{
public:
	//设置点坐标
	void setXY(int x, int y);
	//得到x坐标
	int getX();
	//得到y坐标
	int getY();

private:
	int m_x;
	int m_y;
};

Circle.h:

#pragma once
#include "Point.h"

class Circle
{
public:
    //设置x,y的值,即设置圆心的坐标
	void setXY(int x, int y);
    //设置圆的半径r
	void setR(int r);
    //判断点是否在圆内  
	bool IsInsideCircle(Point &p);
private:
	int m_x;
	int m_y;
	int m_r;
};

Point.cpp:

#include "Point.h"
void Point::setXY(int x, int y){
		m_x = x;
		m_y = y;
	}

int Point::getX(){
		return m_x;
	}

int Point::getY(){
		return m_y;
	}

Circle.cpp:

#include "Circle.h"

void Circle::setXY(int x, int y){
		m_x = x;
		m_y = y;
	}

void Circle::setR(int r){
		m_r = r;
	}

bool Circle::IsInsideCircle( Point &p){
		if( m_r*m_r > (m_x - p.getX())*(m_x - p.getX()) + (m_y - p.getY())*(m_y - p.getY()) ){
			return true;
		}
		else{
			return false;
		}
	}

main.cpp:

#include <iostream>
#include "Point.h"
#include "Circle.h"
using namespace std;

int main(void){
	Point p;
	p.setXY(2,2);
	Circle c;
	c.setXY(0,0);
	c.setR(10);
	if(c.IsInsideCircle(p)){
		cout<< "点 (" << p.getX() << "," << p.getY() << ")在圆内" << endl;
	}
	else{
		cout <<  "不在圆中" << endl;
	}

	return 0;
}

例4:编写C++程序完成下面的功能:
1)定义一个Point类,其属性包括点的坐标,提供计算两点之间的距离方法;
2)定义一个圆形类,其属性包括圆心和半径;
3)创建两个圆形对象,提示用户输入圆心坐标和半径,判断两个圆是否相交,并输出结果。

#include <iostream>
#include <math.h>
using namespace std;

class Point
{
public:
	//设置点 x,y的值
	void setXY(int x, int y){
		m_x = x;
		m_y = y;
	}
	//计算两点之间的距离
	double  point_distance( Point & another){
		double dis;
		dis = sqrt( (m_x - another.m_x) * (m_x - another.m_x) + (m_y - another.m_y)*(m_y - another.m_y) );
		return dis;
	}
private:
	int m_x;
	int m_y;
};

class Circle
{
public:
	//设置圆心
	void setXY(int x, int y){
		p0.setXY(x, y);
	}
	//设置半径
	void setR(int r){
		m_r  = r; 
	}
	//判断是否相交
	bool isIntersection(Circle &another){
		//半径之和
		int rr = m_r + another.m_r;
		//圆心距离
		double dis = p0.point_distance(another.p0);
		if(dis <= rr){
			return true;
		}
		else{
			return false;
		}
	}
private:
	Point p0;
	int m_r;
};

int main(void){
	Circle c1;
	Circle c2;
	int x,y,r;

	cout << "输入第一个圆的横坐标:" << endl;
	cin >> x;
	cout << "输入第一个圆的纵坐标:" << endl;
	cin >> y;
	c1.setXY(x,y);
	cout << "请输入第一个圆的半径:" << endl;
	cin >> r;
	c1.setR(r);

	cout << "输入第二个圆的横坐标:" << endl;
	cin >> x;
	cout << "输入第二个圆的纵坐标:" << endl;
	cin >> y;
	c2.setXY(x, y);
	cout << "请输入第二个圆的半径:" << endl;
	cin >> r;
	c2.setR(r);

	if(c1.isIntersection(c2)){
		cout << "两圆相交" <<endl;
	}
	else{
		cout << "两圆不相交" <<endl;
	}

	return 0;
}
  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值