C++学习路线之C++基础(六)——引用、函数和封装

九、引用

作用:给变量取别名。

语法:数据类型 &别名 = 原名;

可以通过别名修改变量的值。

9.1、引用的注意事项:

引用必须初始化,且初始化后不可改变。(不能作为其他变量的别名)

#include<iostream>

using namespace std;

int main()
{
	int a = 10;
	int c = 20;
	//int& b; 引用必须初始化
	int& d = a;
	d = c;//这只是赋值操作,会改变a的值,d还是a的别名
	cout << "a=" << a << ",d=" << d << ",c=" << c << endl;
	return 0;

9.2、引用做函数参数

函数传参时,可以利用引用技术让形参修饰实参,可以简化指针的使用。

示例:交换函数

#include<iostream>

using namespace std;
//值传递
void myswap01(int a, int b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}
//地址传递
void myswap02(int *a, int *b)
{
	int temp= *a;
	*a = *b;
	*b = temp;
}
//引用传递
void myswap03(int &a, int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}
int main()
{
	int a = 10;
	int b = 20;
	myswap01(a, b);//值传递,实参不会改变
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	myswap02(&a, &b);//地址传递,实参发生改变
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	myswap03(a, b);//引用传递,实参发生改变
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	return 0;
}

9.3、引用做函数返回值

1、不要返回局部变量的引用。

2、函数的调用可以作为左值。

#include<iostream>

using namespace std;

int& test01()
{
	int a = 10;//局部变量存放在栈区
	return a;
}

int& test02()
{
	static int a = 10;//静态变量存放在全局区
	return a;
}

int main()
{
	int& ref = test01();
	cout << "ref = " << ref << endl;
	cout << "ref = " << ref << endl;//a的内存释放,数据错误

	int& ref2 = test02();
	cout << "ref2 = " << ref2 << endl;
	cout << "ref2 = " << ref2 << endl;//a的内存没有释放
	test02() = 1000;//通过引用,修改静态变量的值,函数调用做了左值
	cout << "ref2 = " << ref2 << endl;
	cout << "ref2 = " << ref2 << endl;
}

9.4、引用的本质:

引用的本质在C++内部实现是一个指针常量。

#include<iostream>

using namespace std;

void func(int& ref)
{
	ref = 100;//ref是引用,转换为*ref=100;
}

int main()
{
	int a = 10;
	int& ref = a;
	//转换为int *const ref = &a;指针常量指向不可修改
	ref = 20;//引用自动转换为 *ref = 20;

	cout << "a = " << a << endl;
	cout << "ref = " << ref << endl;

	func(a);
	cout << "a = " << a << endl;
	cout << "ref = " << ref << endl;
	return 0;
}

9.5、常量引用:

常量引用作用主要是用来修饰形参,防止误操作。

#include<iostream>

using namespace std;

void showValue(const int& val)
{
	//val = 1000;//加入const后,无法通过val修改a的值
	cout << val << endl;
}
int main()
{
	//int a = 10;
	//加上const后,编译器将代码修改为int temp = 10;const int &ref = temp;
	const int& ref = 10;
	//ref = 20;加入const后变为只读,不可修改。
	int a = 100;
	showValue(a);
	return 0;
}

十、函数高级:

10.1、函数的默认参数:

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

语法: 数据类型 函数名(形参名= 默认参数)

#include<iostream>

using namespace std;

int func(int a, int b=20, int c=30)
{
	return a + b + c;
}

int main()
{
	cout << func(10) << endl;//默认参数可以不传
	cout << func(10,30) << endl;//传了默认参数会覆盖默认参数的值
	return 0;
}

注意事项:

1、某个位置已经有了默认参数,从这个位置往后,从左到右,都必须有默认值

void func(int a,int b = 10,int c)

{

        return a+b+c;

}//这种写法是错误的,b有了默认参数,b右边的所有参数必须要有默认参数

2、如果函数声明有默认参数,函数实现不能有默认参数。

10.2、函数占位参数

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

#include<iostream>

using namespace std;

void func(int a, int)
{
	cout << "this is func" << endl;
}

int main()
{
	func(10, 10);
	return 0;
}

占位参数也可以有默认参数

#include<iostream>

using namespace std;

void func(int a, int =10)
{
	cout << "this is func" << endl;
}

int main()
{
	func(10);
	return 0;
}

10.3、函数重载

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

函数重载满足条件:

  • 同一个作用域下
  • 函数名称相同
  • 函数参数类型不同或者个数不同或者顺序不同。
  • 函数的返回值不可以作为函数重载的条件。
#include<iostream>

using namespace std;

void func()
{
	cout << "this is func()" << endl;
}
void func(int a)
{
	cout << "this is func(int a)" << endl;
}
void func(double a)
{
	cout << "this is func(double a)" << endl;
}
void func(int a,double b)
{
	cout << "this is func(int a,double b)" << endl;
}
void func(double a, int b)
{
	cout << "this is func(double a,int b)" << endl;
}
int main()
{
	func();
	func(10);
	func(3.14);
	func(10, 3.14);
	func(3.14, 10);
	return 0;
}

 注意事项:

  • 引用是函数重载条件:
#include<iostream>

using namespace std;

void func(int& a)

{

	cout << "func (int &a)" << endl;

}

void func(const int& a)

{

	cout << "func (const int &a)" << endl;

}

int main()
{
	int a = 10;
	func(a);//调用func(int &a)函数
	func(10);//调用func(const int &a)函数
	return 0;
}
  • 函数重载与默认参数

函数重载遇到默认参数会出现二义性

#include<iostream>

using namespace std;

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

void func2(int a)
{
	cout << "func2 (int a)" << endl;
}
int main()
{
	func2(10,10);//两个参数可以用
	//func2(10)//一个参数无法确认是哪个函数
	return 0;
}

十、类和对象

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

C++认为万事万物都是对象,对象上有其属性和行为。

具有相同性质的对象,可以抽象为类

10.1、封装

封装的意义:

  • 将属性和行为作为一个整体,表现生活中的事物——在设计类的时候,将属性和行为写在一起,表现事物。

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

示例:设计一个圆,求圆的周长。

实例化:通过一个类创造一个对象。

#include<iostream>
#define PI 3.14
using namespace std;
//定义一个圆类
class Circle
{
	//访问权限
public:
	//属性
	double m_r;//半径
	//行为————用函数表示行为
	//获取圆的周长
	double calculateZC()
	{
		return 2 * PI * m_r;
	}
};

int main()
{
	//通过圆类创造具体的圆
	Circle c1;
	//给属性进行赋值
	c1.m_r = 10;
	cout << "圆c1的周长为:" << c1.calculateZC() << endl;
	return 0;
}

示例二:设计一个学生类,属性有姓名和学号,可以给姓名和学号赋值,可以显示学生的姓名和学号(行为)。

#include<iostream>
#include<string>

using namespace std;

class student
{
public:
	string name;
	int s_id;
	void showstudent()
	{
		cout << "学生的姓名是:" << name;
		cout << ",学生的学号是:" << s_id << endl;
	}
};

int main()
{
	student s1;
	s1.name = "zxx";
	s1.s_id = 1;
	s1.showstudent();
	return 0;
}

可以通过行为给属性赋值。

#include<iostream>
#include<string>

using namespace std;

class student
{
public:
	string name;
	int s_id;
	void showstudent()
	{
		cout << "学生的姓名是:" << name;
		cout << ",学生的学号是:" << s_id << endl;
	}
    void setName(string c)
    {
        name = c;
    }

};

int main()
{
	student s1;
	s1.setName("zxx");
	s1.s_id = 1;
	s1.showstudent();
	return 0;
}
  • 将属性和行为加以权限控制

权限有三种:

  1. public:公共权限
  2. protected:保护权限
  3. private:私有权限
#include<iostream>
#include<string>
using namespace std;

class person
{
public://类内可以访问,类外不可以访问
	string name;
protected://类内可以访问,类外不可以访问,可以继承(儿子可以访问)
	string car;
private://类内可以访问,类外不可以访问,不可以继承(儿子不可以访问)
	int password;

public:
	void func()
	{
		name = "zxx";
		car = "biyadi";
		password = 123456;
	}
	void print()
	{
		cout << name << car << password << endl;
	}
};

int main()
{
	person p1;
	p1.name = "ww";
	//p1.car = "benchi";保护权限内容在类外访问不到。
	//p1.password = 111111;私有权限内容在类外访问不到。
	p1.func();
	p1.print();
	return 0;
}

类中的属性和行为都成为成员。

10.1.1、struct和class的区别:

class和struct唯一的区别在于默认的访问权限不同,struct默认权限为公共,class默认权限为私有。

10.1.2、成员属性私有化

优点:

  1. 将所有成员属性设为私有,可以自己控制读写权限
  2. 对于写权限,可以检测数据的有效性
#include<iostream>
#include<string>
using namespace std;

class person
{
private:
	string name;//可读可写
	int age;//只读
	string lover;//只写
public:
	//写姓名
	void setname(string n)
	{
		name = n;
	}
	//读姓名
	string getname()
	{
		return name;
	}
	//读年龄
	int getage()
	{
		age = 0;//初始化为0岁
		return age;
	}
	//写情人
	void setlover(string l_n)
	{
		lover = l_n;
	}
};

int main()
{
	person p;
	//无法直接访问属性,只能通过行为来获取和设置信息
	p.setname("ww");
	cout << "姓名为:" << p.getname() << endl;
	cout << "年龄为:" << p.getage() << endl;
	p.setlover("甘乐");
	return 0;
}

检测数据有效性:

#include<iostream>
#include<string>
using namespace std;

class person
{
private:
	string name;//可读可写
	int age;//可读可写,0-100岁合法
	string lover;//只写
public:
	//读年龄
	int getage()
	{
		//age = 0;//初始化为0岁
		return age;
	}
	void setage(int a)
	{
		if (a >= 0 && a <= 100)
		{
			age = a;
		}
		else
		{
			cout << "年龄非法" << endl;
			age = 0;
		}
	}
};

int main()
{
	person p;
	p.setage(10);
	cout << "年龄为:" << p.getage() << endl;
	return 0;
}

 练习案例一:设计立方体类:

设计立方体,属性为长宽高

求出面积和体积,使用全局函数和成员函数判断两个立方体是否相等。

#include<iostream>

using namespace std;

class Cube
{
private:
	float m_L;
	float m_H;
	float m_W;
public:
	//设置获取长宽高
	void setlength(int length)
	{
		m_L = length;
	}
	void setwidth(int width)
	{
		m_W = width;
	}
	void sethight(int hight)
	{
		m_H = hight;
	}
	//获取
	float getlength()
	{
		return m_L;
	}
	float getwidth()
	{
		return m_W;
	}
	float gethight()
	{
		return m_H;
	}
	//计算表面积
	float calculateS()
	{
		return 2 * (m_L * m_H + m_L * m_W + m_W * m_H);
	}
	//计算体积
	float calculateV()
	{
		return m_L * m_H * m_W;
	}
	//成员函数判断立方体是否相等
	bool equal(Cube &c)
	{
		if (m_L == c.getlength() && m_W == c.getwidth() && m_H == c.gethight())
		{
			cout << "c1和c2是相等的" << endl;
			return true;
		}
		else
		{
			cout << "c1和c2是不相等的" << endl;
			return false;
		}
	}
};

//利用全局函数判断立方体是否相等
bool isSame(Cube c1, Cube c2)
{
	if (c1.gethight() == c2.gethight() && c2.getlength() == c1.getlength() && c1.getwidth() == c2.getwidth())
	{
		cout << "c1和c2是相等的" << endl;
		return true;
	}
	else
	{
		cout << "c1和c2是不相等的" << endl;
		return false;
	}
}

int main()
{
	Cube c1;
	c1.sethight(10);
	c1.setlength(10);
	c1.setwidth(10);
	cout << "c1的面积为:" << c1.calculateS() << endl;
	cout << "c1的体积为:" << c1.calculateV() << endl;
	Cube c2;
	c2.sethight(10);
	c2.setlength(10);
	c2.setwidth(10);
	//全局函数判断相等
	isSame(c1, c2);
	//成员函数判断是否相等
	c1.equal(c2);
	return 0;
}

练习案例二:点与圆的关系

用 圆心坐标 x1和y1,点也有一个坐标x2,y2,圆有一个半径,点到圆心的距离与半径进行比较。

距离

​​​​​​为了简便,可以用距离平方和半径的平方

point.h

#pragma once
#include<iostream>

class Point
{
private:
	int x;
	int y;
public:
	//设置
	void setx(int a);
	void sety(int a);
	//获取
	int getx();
	int gety();
};

point.cpp

#include"point.h"

void Point:: setx(int a)
{
	x = a;
}
void Point::sety(int a)
{
	y = a;
}
//获取
int Point::getx()
{
	return x;
}
int Point::gety()
{
	return y;
}

circle.h

#pragma once
#include<iostream>
#include"point.h"
class Circle
{
private:
	int m_R;//半径
	//在类中,可以让另一个类作为本类的成员
	Point m_Center;//圆心坐标
public:
	//设置半径
	void setr(int r);
	//设置圆心
	void setcenter(Point center);
	//获取半径
	int getr();
	//获取圆心
	Point getcenter();
};

circle.cpp

#include"circle.h"
//设置半径
void Circle::setr(int r)
{
	m_R = r;
}
//设置圆心
void Circle::setcenter(Point center)
{
	m_Center = center;
}
//获取半径
int Circle::getr()
{
	return m_R;
}
//获取圆心
Point Circle::getcenter()
{
	return m_Center;
}

main.cpp

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

void isInCircle(Circle& 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()
{
	Circle c;
	c.setr(10);
	Point center;
	center.setx(10);
	center.sety(0);
	c.setcenter(center);
	Point p;
	p.setx(10);
	p.sety(10);
	isInCircle(c, p);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值