C++函数

C++函数

1.内联函数
使用内联函数必须采取下列叙述之一

1)在函数声明前加上关键字inline
2)在函数定义前加上关键字inline
通常做法是省略原型,将整个定义放在原型的位置,如果函数定义占用多行,使用内联函数就不太合适(由内联函数的使用方法决定)。

//定义内联函数
inline double square(double x)
{
	return x * x;
}

内联与宏:
内联函数是按值来传递参数的,如4.5+7.5,函数传递表达式的值。
宏是通过文本的替换来实现的,如 c = square(c++),那么这个表达式将会被替换为c = c++*c++,显然是有问题的。

2.引用变量

引用是已定义变量的别名(另一个名称)。主要用途是用作函数的形参,函数将使用原始数据,而不是副本。

创建引用变量

C++给&符号赋予了另外一个新的含义,将其用来声明引用。如将rodents作为rats的别名,可以这样做:

int rats;
int &rodents = rats;
int *prats = &rats;

&符号在这里就不是地址运算符了,而是声明rodents是指向int的引用变量。rodents和*prats’与rats等价,而表达式prats和&rodents与&rats等价,表示地址。引用和指针的区别在于:
声明必须在引用时将其初始化,而指针可以先声明,再赋值:

int rat;
int &rodent;
rodent = rat;//无法这样赋值  必须在声明时将其初始化
如果改变变量引用
//内联函数的使用
# include "pch.h"
# include <iostream>
# include <string>

using namespace std;

int main()
{
	int rats = 101;
	int &rodents = rats;
	cout << "rats = " << rats;
	cout << ", rodents = " << rodents << endl;
	
	cout << "rats adress = " << &rats;   //&是地址运算符,不是声明运算符
	cout << " , rodents adress = " << &rodents << endl;

	int bunnies = 50;
	rodents = bunnies;  //初始化时是rats的别名,现在能改变指向的别名么?
	cout << "bunnies = " << bunnies;
	cout << ", rats = " << rats;
	cout << ", rodents = " << rodents << endl;

	cout << "bunnies address = " << &bunnies;
	cout << ", rodents adress = " << &rodents << endl;
	return 0;
}

因为rodents已经是rats的别名,二者的地址相同,程序中的赋值语句等价于

rats = bunnies;

这说明,可以通过初始化声明来设置引用,但不能通过赋值来设置(赋值时地址并不是新值的地址,达不到引用的效果)。

将引用作为函数参数

首先分清按引用传递、按指针传递、按值传递的区别:

void swapr(int &a, int &b)  //按引用传递
{
	int temp;
	temp = a;
	a = b;
	b = temp;   //相当于交换了两个钱包的数值
}
void swapp(int *p, int *q)
{
	int temp;
	temp = *p;
	*p = *q;   //解除指针引用
	*q = temp;
}
void swapv(int a, int b)  //a,b是复制了wallet1,wallet2的新变量
{                         //交换a,b的值不会影响wallet1,wallet2
	int temp;
	temp = a;
	a = b;
	b = temp;   
}
double cube(double a)  //a在cube()中,按值传递将x复制给a但是并没有改变x的值
{                      //因此修改a不会改变x的值
	a *= a * a;
	return a;
}
//double recube(const double &ra) 防止修改
double recube(double &ra)
{
	ra *= ra * ra;
	return ra;  //ra是引用,在这里修改了ra的值就是修改了x的值
}

临时变量、引用参数和const
编译器在以下两种情况的时候会生成临时变量:
1.实参的类型正确,但不是左值(除了用括号括起的字符串之外的字面常量,包含多项的表达式)。
2.实参的类型不正确,但是可以转换成为正确的类型。
应该尽可能的使用const:
1.使用const可以避免无意中修改数据的编程错误。
2.使用const使函数能够处理const和非const实参,否则只能接受非const数据。
3.使用const引用使函数能够正确生成并使用临时变量。

将引用用于结构

使用结构引用参数的方式和基本变量的引用方式类似,只需要在声明结构参数时使用引用运算符&即可。例如有如下结构体:

struct free_throws
{
	string name;
	int made;
	int attempts;
	float percent;
};

可以编写这样的函数原型,在函数中将指向该结构的引用作为参数:

void set_pc(free_throws & ft);
void display(const free_throws &ft); //不改变传入的参数
将引用用于类对象

程序不能调用一个已经释放内存的引用,如

const string & version3(string & s1, const string & s2)
{
	string temp;
	temp = s2 + s1 + s2;
	return temp;
}

这是返回一个引用的函数,但是在函数中temp是一个临时变量,函数运行之后便释放内存,因此会导致程序崩溃。

3.默认参数

当函数调用时省略实参时自动使用的一个值,比如下面的函数原型:

int harpo(int n,int m = 4,int j=5;

在调用函数时,实参可以省略后面两个整型值,函数会自动默认为4和5。
注:对于带实参列表的函数,必须从右向左添加默认值。因为在实参列表中按从左到右的顺序依次赋值给相应的形参。下面的调用是禁止的:

beeps = harpo(3, ,8);
4. 函数重载

函数重载和函数多态是一个意思,就是同一个函数名局部有不同的参数列表,完成不同的工作,如何识别到底是什么工作,则需要根据上下文来确定(参数列表)。
说明:
1.如果调用的实参和参数类型不匹配,虽然C++可以强制类型转换,但是当实参与多个函数的特征标都相匹配时,程序会报错。
2.一些看起来彼此不同的特征标是不能共存的。编译器在检查特征标的时候将类型引用和类型的本身看成是一个特征标,类似的,匹配函数时也不区分const和非const变量。(将非const赋值给const是合法的)
3.特征标的不同,函数才可以重载。

long gronk(int n,float m);
double gronk(int n,float m);//只是返回类型不同,特征标相同,不是函数重载

long gronk(int n,float m);
double gronk(float n,float m);//特征标不同,是函数重载
5.函数模板

函数模板是通用的函数,使用函数泛型来定义函数,可以与int或double等数据类型替换。当调用函数时,通过实参的类型,编译器可以判断形成该类型的函数。

template<typename AnyTpye>   //建立一个模板 类型名为AnyType
void Swap(AnayType &a,AnyType &b)
{
   AnyType temp;
   temp = a;
   a = b;
   b = temp;
}

typename使得参数AnyType表示这一类型更为明显;然而有大量的代码库是使用关键字class开发的,在上下文中,这两个关键字是等价的。

重载的函数模板

对多个不同类型的使用同一种算法的函数时,可以使用模板。但并非所有的类型都使用相同的算法,这里可以使用函数重载满足不同的算法,特征标必须不同。

// 程序说明:默认参数的调用。
//

#include "pch.h"
#include <iostream>

template <typename T>
void Swap(T &a, T &b);

template <typename T>
void Swap(T *a, T*b, int n);

void Show(int a[]);

const int Lim = 8;
int main()
{
	using namespace std;
	int i = 10;
	int j = 20;
	cout << "i,j = " << i << " , " << j << endl;
	cout << "Using compiler-generated int swapper:\n";  //编译器自动生成int函数模板转换
	Swap(i, j);   //不能用系统自定义的函数名称
	cout << "Now i,j = " << i << " , " << j << endl;

	int d1[Lim] = { 1,0,0,1,1,9,4,9 };
	int d2[Lim] = { 1,0,0,1,2,0,1,9 };
	cout << "Original arrays is:" << endl;
	Show(d1);
	Show(d2);
	Swap(d1, d2, Lim);
	cout << "Swapped arrays:" << endl;
	Show(d1);
	Show(d2);
	return 0;
}

template <typename T>
void Swap(T &a, T &b)
{
	T temp;
	temp = a;
	a = b;
	b = temp;
}

template <typename T>
void Swap(T *a, T*b, int n)
{
	T temp;
	for (int i = 0; i < n; i++)
	{
		temp = a[i];
		a[i] = b[i];
		b[i] = temp;
	}
}

void Show(int a[])
{
	using namespace std;
	cout << a[0] << a[1] << "/";
	cout << a[2] << a[3] << "/";
	for (int i = 4; i < Lim; i++)
		cout << a[i];
	cout << endl;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值