引用就是对一个变量进行取别名,类似于对一个人取外号,无论你是叫他大名还是外号,都是指他。例如张三的外号就是法外狂徒,那么张三身高一米九,同样法外狂徒的身高也是一米九,同理如果法外狂徒本来不近视现在近视了,那么张三也变近视了。意思就是说一个变量引用和这个变量是同一个东西,任何一个改变另一个也会随着改变。引用之后法外狂徒就只能是指张三,不能改变,让这个外号成为李四的。
1.引用是一种类型:引用类型 用int类型举例它对应的引用类型就是int&
2.引用必须初始化,在起这个外号时,就要确定这个外号是谁的,并且确定这个外号是谁的之后,就不可以把这个外号给别人
3.一个人可以有多个外号,引用也是,一个变量可以有多个引用名
4.不能给法外狂徒起外号,即不能定义引用的引用
通过交换值这个例子进一步解释:
#include
using std::cout;
using std::endl;
void Swap(int &x, int &y)
{
int tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 1;
int b = 2;
Swap(a, b);
cout << a << endl;
cout << b << endl;
return 0;
}
重要:形参初始化的机理与变量初始化一样。形参的类型决定了形参和实参交互的方式。如果形参是引用类型,它将绑定到对应的实参上;否则,将实参的值拷贝赋给形参。
也就是说这里的引用类型形参x,y就是实参a,b的别名,形参改变实参也会改变。
C++引出了域的概念,即一个变量只能在它对应的域上才能起作用,不同的域可以定义相同名的变量,并使用namespace关键字 + 命名空间名称+{}来规定域的范围。名字的作用域就是指变量的作用域。命名空间定义了一个新的作用域
1、
#include
using std::cout;
using std::endl;
int a = 3;
namespace var
{
int a = 1;
}
int main()
{
int a = 0;
cout << a << endl;//输出a = 0;
return 0;
}
2、
#include
using std::cout;
using std::endl;
int a = 3;
namespace var
{
int a = 1;
}
int main()
{
//int a = 0;
cout << a << endl;//输出a = 3;
return 0;
}
3、
#include
using std::cout;
using std::endl;
//int a = 3;
namespace var
{
int a = 1;
}
int main()
{
//int a = 0;
cout << a << endl;
return 0;
}
此时说a未定义,也就是当变量在另一个域时,它不会自动去和自己同级别或者小于它级别的域中去寻找是否包含该变量。
域分为全局作用域和块作用域,全局作用域可以使用在整个程序中,块作用域中的变量只在这个块作用域内才能被访问。
嵌套作用域:一个作用域的里面可以包含另外一个或多个的作用域,外层的作用域可以在内层作用域里面被访问。这种关系和块作用域与全局作用域之间的关系相同。
如果想在一个域内访问它外部域的变量,就要通过命名空间名称加上作用域操作符::。
#include
using std::cout;
using std::endl;
//int a = 3;
namespace var
{
int a = 1;
}
int main()
{
int a = 0;
cout << a << endl;
cout << var::a << endl;//对这个域进行访问 此时输出结果为1
return 0;
}
通过上述三个例子我们可以得出当对一个变量进行访问时,对该变量的搜索顺序
指定域>局部域>全局域>其它域 (当在局部域和全局域找不到该变量时,编译器不会主动去寻找其它域中是否包含该变量)
给定形参一个默认值,当没有传实参时就把形参值作为实参。
缺省参数是在声明或定义时为函数参数给定一个默认值。
注意声明和定义只能选择一个去给定缺省参数,推荐在定义时给
缺省参数与函数重载不同,函数重载必须在定义时构成重载才有效,在声明时构成在定义时不构成不起作用。
#include
using std::cout;
using std::endl;
int Add(int x = 5, int y = 6)
{
return x + y;
}
int main()
{
int ret1 = Add();
cout << ret1 << endl;//输出11
int a = 3;
int ret2 = Add(a);
cout << ret2 << endl;//输出9
return 0;
}
int Add(int x, int y = 6)
{
return x + y;
}
也可以只给定部分默认值,但是要从右向左给默认值。因为当传入一个值时会从左向右拷贝给形参。
int Add(int x = 5, int y = 6)
{
return x + y;
}
int Add(int x, int y = 6)
{
return x + y;
}
以上代码不构成重载因为重载的定义时参数个数或类型不同,与是否缺省无关。
C++中允许函数名相同,但前提是要满足重载,当函数名相同时但函数参数个数不同或类型不同可构成重载,与返回值类型无关,返回值类型可以相同也可以不同。
//函数重载
#include
using std::cout;
using std::endl;
void Swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
void Swap(double& x, double& y)
{
double tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 5;
int b = 6;
cout << a << "," << b << endl;
Swap(a, b);
cout << a << "," << b << endl;
cout << endl;
double c = 1.2f;
double d = 3.1f;
cout << c << "," << d << endl;
Swap(c, d);
cout << c << "," << d << endl;
return 0;
}
此外要注意函数重载必须要在函数定义时构成重载才有效,只在声明时构成重载不起作用。
声明:
void Swap(int& x, int& y);
void Swap(double& x, double& y);
定义时只有一个参数为int的:
void Swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
C语言不会到这一步,因为当声明时函数名相同它就会报错,C不支持重载。
我们现在对刚才函数重载中出现的无法解析的外部符号进行理解。
C++中在编译的时候会生成符号表,函数名字相同但参数类型或个数不同,对应生成的符号表也就不同,C++函数在调用时是去符号表中去找这个与函数对应生成的符号去调用,如果没找到在链接时就会出错,这也就是为什么C++支持重载的原因。