(2)函数参数、重载,类和对象-封装

函数的默认参数

在C++中,函数的形参列表中的形参是可以有默认值的

语法:返回值类型 函数名 (参数=默认值){}

//如果某个位置已经有了默认参数,则从这个位置往后,从左到右都必须要有默认值
//int func2(int a, int b = 10, int c,int d){}  错误
//int func2(int a, int b = 10, int c = 10,int d = 10){}  正确
//int func2(int a, int b, int c, int d = 10) {}   正确

//如果函数声明有默认参数,函数实现就不能有默认参数(声明和实现只能有一个有默认参数)
int func2(int a = 10, int b = 10);//函数声明
int func2(int a, int b = 20) //函数实现//这里打出来的代码不会显示有错,但运行会出错
{//错误	C2572	“func2” : 重定义默认参数: 参数 1
	return a + b;
}

int func(int a, int b = 50, int c = 10) {
	return a + b + c;
}
int main() {
	//如果我们自己传入数据,就用传入的数据,如果没有,就用默认值
	cout << func(10) << endl;//10+50+10=70
	cout << func(10, 20) << endl;//10+20+10=40
	cout << func(10, 20, 30) << endl;//10+20+30=60
	return 0;
}

函数占位参数

C++中参数的形参列表里可以有占位参数,用来占位,调用函数时必须填补该位置

语法:返回值类型 函数名 (数据类型){}

//占位参数,可以有默认参数,如:void func(int a, int = 10){}
void func(int a,int) {
	cout << "this is func" << endl;
}
int main() {
	func(10,10);//占位参数int没有值,因此这里需要传入两个参数填补占位参数,不然会报错
	//如果是第一行是 void func(int a, int = 10),这里就可以写成 func(10);
	return 0;
}

函数重载

函数名可以相同,提高复用性

函数重载满足条件:

  • 同一个作用域下
  • 函数名称相同
  • 函数参数类型不同,或者参数个数不同,或者参数顺序不同

注意:函数的返回值不可以作为函数重载的条件

//main函数外面都是全局作用域
//函数名称相同
void func() { cout << "函数 1 " << endl; }//0参数
void func(int a) { cout << "函数 2 " << endl; }// 1 个参数,函数 1 和 2 的参数个数不同
void func(double a) { cout << "函数 3 " << endl; }//函数 2 和 3 的参数类型不同
void func(int a, double b) { cout << "函数 4 " << endl; }
void func(double a, int b) { cout << "函数 5 " << endl; }//函数 4 和 5 的参数顺序不同
//int func(double a, int b) { cout << "函数 5 " << endl; }//返回值不能作为重载条件
int main() {
	func();//打印 函数 1
	func(10);//打印 函数 2
	func(3.14);//打印 函数 3
	func(3.14,10);//打印 函数 5
	func(10,3.14);//打印 函数 4
	func(0.11, 10);//打印 函数 5
	return 0;
}

函数重载注意事项

  • 引用可以作为重载条件
  • 函数重载碰到函数默认参数
void func1(int &a) { cout << "函数 1 " << endl; }
void func1(const int &a) { cout << "函数 2 " << endl; }
//重载遇到默认参数,出现二义性,尽量避免
void func2(int a, int b = 20) { cout << "函数 3 " << endl; }
void func2(int a) { cout << "函数 4 " << endl; }
int main() {
	int a = 10;//变量 a 可读可写
	func1(a);//打印 函数 1 
	//因为变量可读可写,而函数 2 加了const,是只读状态,所以调用函数 1
	func1(10);//打印 函数 2 
	//int &a = 10;不合法  const int &a = 10;合法
	func2(10, 30);//打印 函数 3 
	//func2(10); //此行报错,因为这样写函数 3 和 4 都可被调用
	return 0;
}

类和对象——封装

类中的属性和行为统一称为成员

  • 属性(或称为 成员属性、成员变量)
  • 行为(或称为 成员函数、成员方法)

C++面向对象的三大特性:封装、继承、多态

C++中,万事万物皆为对象,对象上有其属性和行为

对象:人,属性:姓名、性别、身高、年龄……,行为:走路、跑步、吃饭……

对象:车,属性:轮胎、方向盘、车灯……,行为:载人、放音乐、拉货……

具有相同性质的对象,可以抽象称为,如人属于人类,车属于车类

封装的意义:

  • 将属性和行为作为一个整体,表现生活中的事物
  • 将属性和行为加以权限控制

封装意义一:

设计类时,属性和行为写在一起,表现事物

语法:class 类名{ 访问权限:属性 / 行为 };

示例一:设计一个圆类,求圆的周长
//圆周长公式:2 * PI * 半径
const double PI = 3.14;
class Yuan {//class代表设计一个类,类后面跟着类名称
public:
	int r;//属性,半径
	double C() {//行为,计算周长
		return 2 * PI * r;
	}
};
int main() {
	//通过圆类Yuan,创建具体的圆(对象)
	Yuan c1;//实例化(通过一个类,创建一个对象的过程)
	c1.r = 10;//给圆对象的属性赋值
	cout << "圆的周长为:" << c1.C() << endl;//打印 圆的周长为:62.8
	return 0;
}
示例二:设计一个学生类,属性有姓名和学号,可以给姓名和学号赋值,可以显示学生的姓名和学号
class Student {
public://类中的属性和行为统一称为成员
	//属性(或称为 成员属性、成员变量)
	string S_Name;//姓名是字符串,用string
	int S_Id;
	//行为(或称为 成员函数、成员方法)
	void showStudent() {
		cout << "姓名:" << S_Name << "   学号:" << S_Id << endl;
	}
	//通过行为给属性赋值
	void setName(string name) {
		S_Name = name;
	}
	void setId(int id) {
		S_Id = id;
	}
};
int main() {
	Student s1;//实例化对象
	s1.S_Name = "星星";//给s1对象进行属性赋值
	s1.S_Id = 1;
	s1.showStudent();

	Student s2;//实例化对象
	s2.setName("月亮");//调用赋值函数
	s2.setId(2);
	s2.showStudent();
}

封装意义二:

类在设计时,可以把属性和行为放在不同的权限下,加以控制

访问权限有三种:

public —— 公共权限         类内可以访问  类外可以访问

protected —— 保护权限   类内可以访问  类外不可以访问(继承,儿子可以访问父亲保护内容)

private —— 私有权限       类内可以访问  类外不可以访问(继承,儿子不可以访问父亲私有内容)

class Person {
public:
	string P_Name;
protected:
	string P_Car;//车
private:
	int P_Pwd;//银行卡密码
public:
	void func() {//公共函数
		P_Name = "李四";
		P_Car = "奥迪";
		P_Pwd = 123456;
	}
};//Person类大括号内是类内
int main() {
	Person p1;//实例化具体对象
	p1.P_Name = "张三";
	p1.P_Car = "宝马";//错误 “Person::P_Car”: 无法访问 protected 成员(在“Person”类中声明)
	p1.P_Pwd = 000000;//错误 “Person::P_Pwd”: 无法访问 private 成员(在“Person”类中声明)	
}
struct和class区别

在C++中struct和class唯一的区别是默认的访问权限不同

  • struct默认权限为公共
  • class默认权限为私有
class C1 {
	int A;
};
struct C2 {
	int A;
};
int main() {
	C1 c1;
	c1.A = 10;//错误“C1::A”: 无法访问 private 成员(在“C1”类中声明)
	C2 c2;
	c2.A = 10;
}
成员属性设置为私有
  • 可以自己控制读写权限
  • 对于写的权限,可以检测数据有效性
class Person {
public://创建公共接口
	void setName(string name) {//设置姓名 写
		P_Name = name;
	}
	string getName() {//获取姓名 读
		return P_Name;
	}
	int getAge() {//获取年龄,只读
		P_Age = 10;//初始化年龄
		return P_Age;
	}
	//如果不加setAge函数,年龄就只能是只读状态
	//void setAge(int age) {//设置年龄
	//	if (age < 0 || age>150) {
	//		cout << "您的年龄不符合规定!" << endl;
	//		return;
	//	}
	//}
	void setLover(string lover) {//设置爱人 只写
		P_Lover = lover;
	}
private:
	string P_Name;//赋予可读可写权限
	int P_Age;//赋予只读权限
	string P_Lover;//赋予只写权限
};
int main() {
	Person p;
	p.setName("李四");//写
	cout << "Name:" << p.getName() << endl;//读
	p.P_Age = 10;//不可 写,报错
	cout << "Age:" << p.getAge() << endl;
	p.setLover("星星");
	cout << "Lover:" << p.getLover() << endl;//不可 读, 报错
}
案例一:设计立方体类(Cube)

求立方体面积和体积

分别用全局函数和成员函数判断两个立方体是否相等


//立方体类
class Cube {
public:
	void setL(int l) {//设置长
		m_L = l;
	}
	int getL() {//获取长
		return m_L;
	}
	void setW(int w) {//设置宽
		m_W = w;
	}
	int getW() {//获取宽
		return m_W;
	}
	void setH(int h) {//设置高
		m_H = h;
	}
	int getH() {//获取高
		return m_H;
	}
	int calculateS() {
		return 2 * m_L * m_W + 2 * m_W * m_H + 2 * m_L * m_H;
	}
	int calculateV() {
		return m_L * m_W * m_H;
	}
	//成员函数判断是否相等
	bool isSameByClass(Cube &c) {
		if (m_L == c.getL() && m_W == c.getW() && m_H == c.getH()) {
			return true;
		}
		return false;
	}
private:
	int m_L;//长
	int m_W;//宽
	int m_H;//高
};
bool isSame(Cube &c1, Cube &c2) {//全局函数判断是否相等
	if (c1.getL() == c2.getL() && c1.getW() == c2.getW() && c1.getH() == c2.getH()) {
		return true;
	}
	else
		return false;
}
int main() {
	Cube c1;//创建立方体对象
	c1.setL(10);
	c1.setW(10);
	c1.setH(10);
	cout << "立方体c1的面积:" << c1.calculateS() << endl;
	cout << "立方体c1的体积:" << c1.calculateV() << endl;
	Cube c2;//第一个立方体
	c2.setL(10);
	c2.setW(10);
	c2.setH(10);
	cout << "立方体c2的面积:" << c2.calculateS() << endl;
	cout << "立方体c2的体积:" << c2.calculateV() << endl;
	bool ret = isSame(c1, c2);
	if (ret) {
		cout << "c1和c2是相等的" << endl;
	}
	else {
		cout << "c1和c2是不相等的" << endl;
	}
	ret = c1.isSameByClass(c2);
	if (ret) {
		cout << "成员函数判断:c1和c2是相等的" << endl;
	}
	else {
		cout << "成员函数判断:c1和c2是不相等的" << endl;
	}
}
案例二:点和圆的关系(计算点到圆心的距离)

设计一个圆类(Cricle)一个点类(Point),判断点和圆的关系

圆心(x1,y1),点(x2,y2)

写法一:

class Point {//点类数据类型
public:
	void setX(int x) {
		m_X = x;
	}
	int getX() {
		return m_X;
	}
	void setY(int y) {
		m_Y = y;
	}
	int getY() {
		return m_Y;
	}
private:
	int m_X;
	int m_Y;
};
class Cricle {//圆类
public:
	void setR(int r) {
		m_R = r;
	}
	int getR() {
		return m_R;
	}
	void setCenter(Point center) {
		m_Center = center;
	}
	Point getCenter() {
		return m_Center;
	}
private:
	int m_R;//半径
	//在类中,可以让另一个类作为本类中的成员
	Point m_Center;//圆心
};
//判断点和圆关系函数
void isInCricle(Cricle &c, Point &p) {
	int distance =
		(c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
		(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
	int rDistance = c.getR() * c.getR();
	if (distance == rDistance) {
		cout << "点在圆上" << endl;
	}
	else if (distance > rDistance) {
		cout << "点在圆外" << endl;
	}
	else {
		cout << "点在圆内" << endl;
	}
}
int main() {
	Cricle c;//圆
	c.setR(10);//半径为10
	Point center;//圆心
	center.setX(10);
	center.setY(0);
	c.setCenter(center);
	Point p;//点
	p.setX(10);
	p.setY(10);
	isInCricle(c, p);//调用判断函数
}

写法二(分开写):

源.cpp

#include<iostream>
using namespace std;
#include"Point.h"
#include"Cricle.h"
//判断点和圆关系函数
void isInCricle(Cricle &c, Point &p) {
	int distance =
		(c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
		(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
	int rDistance = c.getR() * c.getR();
	if (distance == rDistance) {
		cout << "点在圆上" << endl;
	}
	else if (distance > rDistance) {
		cout << "点在圆外" << endl;
	}
	else {
		cout << "点在圆内" << endl;
	}
}
int main() {
	Cricle c;//圆
	c.setR(10);//半径为10
	Point center;//圆心
	center.setX(10);
	center.setY(0);
	c.setCenter(center);
	Point p;//点
	p.setX(10);
	p.setY(10);
	isInCricle(c, p);//调用判断函数
}

point.h

#pragma once
#include<iostream>
using namespace std;
class Point {//点类
public:
	void setX(int x);
	int getX();
	void setY(int y);
	int getY();
private:
	int m_X;
	int m_Y;
};

point.cpp

#include"point.h"

void Point::setX(int x) {
	m_X = x;
}
int Point::getX() {
	return m_X;
}
void Point::setY(int y) {
	m_Y = y;
}
int Point::getY() {
	return m_Y;
}

cricle.h

#pragma once
#include<iostream>
using namespace std;
#include"point.h"
class Cricle {//圆类
public:
	void setR(int r);
	int getR();
	void setCenter(Point center);
	Point getCenter();
private:
	int m_R;//半径
	//在类中,可以让另一个类作为本类中的成员
	Point m_Center;//圆心
};

cricle.cpp

#include"cricle.h"

void Cricle::setR(int r) {
	m_R = r;
}
int Cricle::getR() {
	return m_R;
}
void Cricle::setCenter(Point center) {
	m_Center = center;
}
Point Cricle::getCenter() {
	return m_Center;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值