文章目录
1.缺省参数
1.缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)
#define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; void sui(int a=0) {//int a=0为默认传参 cout << a << endl; } int main() { sui();//没有传参时,使用默认参数 sui(10);//有传参时,使用指定传参 return 0; } 输出:0 10
2.全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。
3.带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参。
#define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; // 全缺省 void sui1(int a = 10,int b = 20,int c = 30) { //int a = 10,int b = 20,int c = 30为默认参数 cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; } // 半缺省,一定有传参 void sui2(int a , int b = 20, int c = 30) { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; } void sui3(int a = 10, int b , int c = 30) { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; } //从右往左依次连续缺省,不能间隔跳跃给缺省值,如sui4(10, ,20);是会报错的 void sui4(int a, int b = 10, int c) { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; } int main() { sui1(); sui1(1); sui1(1,2); sui1(1,2,3); //sui2();错误的,半缺省一定有传参 sui2(10); sui2(10,20); sui2(10,20,30); //sui4(10, ,20); return 0; }
4.函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值
// Stack.h #include <iostream> #include <assert.h> using namespace std; typedef int STDataType; typedef struct Stack { STDataType* a; int top; int capacity; }ST; void STInit(ST* ps, int n = 4); // Stack.cpp #include"Stack.h" // 缺省参数不能声明和定义同时给 //void STInit(ST* ps, int n = 4)会报错,表示重定义默认参数 void STInit(ST* ps, int n) { assert(ps && n > 0); ps->a = (STDataType*)malloc(n * sizeof(STDataType)); ps->top = 0; ps->capacity = n; } // test.cpp #include"Stack.h" int main() { ST s1; STInit(&s1); // 确定知道要插⼊1000个数据,初始化时⼀把开好,避免扩容 ST s2; STInit(&s2, 1000); return 0; }
程序报错:重定义默认参数
2.函数重载
C++支持在同一作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。这样C++函数调用就表现出了多态行
为,使用更灵活。C语言是不支持同一作用域中出现同名函数的。
2.1重载条件:
1.参数类型不同
cpp会根据函数中参数类型进行函数的匹配
#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
int main() {
//跳入int Add(int left, int right)
Add(10, 20);
//跳入double Add(double left, double right)
Add(10.1, 20.2);
return 0;
}
2.参数个数不同
cpp会根据函数中参数类个数进行函数的匹配
#include<iostream>
using namespace std;
// 2、参数个数不同
void sui()
{
cout << "sui()" << endl;
}
void sui(int a)
{
cout << "sui(int a)" << endl;
}
int main() {
//跳入void sui()
sui();
//跳入void sui(int a)
sui(10);
return 0;
}
3.参数类型顺序不同
#include<iostream>
using namespace std;
// 3、参数类型顺序不同
void sui(int a, char b)
{
cout << "sui(int a,char b)" << endl;
}
void sui(char b, int a)
{
cout << "sui(char b, int a)" << endl;
}
int main() {
sui(10, 'a');
sui('a', 10);
return 0;
}
2.2不做重载条件情况:
1.返回值相同时
// 返回值不同不能作为重载条件,因为调⽤时也⽆法区分
void sui()
{}
int sui()
{
return 0;
}
2.当全缺省遇见无参数
// 下⾯两个函数构成重载
// f()但是调⽤时,会报错,存在歧义,编译器不知道调⽤谁
void sui()
{
cout << "sui()" << endl;
}
void sui(int a = 10)
{
cout << "sui(int a)" << endl;
}
3.引用
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
例如:水浒传中,江湖上人称"黑旋风";林冲,外号豹子头;
类型&引用别名 = 引用对象; 注:这里的&与取地址操作符一致
#include<iostream>
using namespace std;
int main() {
int a = 10;
// 引⽤:b和c是a的别名
int& b = a;
int& c = a;
// 也可以给别名b取别名,d相当于还是a的别名
int& d = b;
// 这⾥取地址我们看到是⼀样的
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
cout << &d << endl;
return 0;
}
3.1引用特性:
- 引用在定义时必须初始化
- 一个变量可以有多个引用
- 引用一旦引用一个实体,再不能引用其他实体
#include<iostream>
using namespace std;
int main()
{
int a = 10;
// 编译报错:“ra”: 必须初始化引⽤
//int& ra;
int& b = a;
int c = 20;
// 这⾥并⾮让b引⽤c,因为C++引⽤不能改变指向,
// 这⾥是⼀个赋值
b = c;
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
return 0;
}
3.2引用的使用:
引用在实践中主要是于引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同时改变被 引用对象。
引用传参跟指针传参功能是类似的,引用传参相对更方便一些。
引用返回值的场景相对比较复杂,我们在这里简单讲了一下场景,还有一些内容后续类和对象章节中会继续深入讲解。
引用和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。C++的引用跟其他语言的引用(如Java)是有很大的区别的,除了用法,最大的点,C++引用定义后不能改变指向, Java的引用可以改变指向。
一些主要用C代码实现版本数据结构教材中,使用C++引用替代指针传参,目的是简化程序,避开复杂的指针,但是很多同学没学过引用,导致一头雾水。
如交换函数:
//swap(&x,&y);
//void Swap(int* rx, int* ry)
//{
//
//int* tmp = rx;
//rx = ry;
//ry = tmp;
//
//}
void Swap(int& rx, int& ry)
{
int tmp = rx;
rx = ry;
ry = tmp;
}
int main()
{
int x = 0, y = 1;
cout << x <<" " << y << endl;
Swap(x, y);
cout << x << " " << y << endl;
return 0;
}
指针和引用的关系
- C++中指针和引用就像两个性格迥异的亲兄弟,指针是哥哥,引用是弟弟,在实践中他们相辅相成,功能有重叠性,但是各有自己的特点,互相不可替代。
- 语法概念上引用是一个变量的取别名不开空间,指针是存储一个变量地址,要开空间。
- 引用在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
- 引用在初始化时引用一个对象后,就不能再引用其他对象;而指针可以在不断地改变指向对象。
- 引用可以直接访问指向对象,指针需要解引用才是访问指向对象。
- sizeof中含义不同,引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节,64位下是8byte)
- 指针很容易出现空指针和野指针的问题,引用很少出现,引用使用起来相对更安全一些