1.c++入门(中)
一.函数重载
1.函数重载概念
c语言不支持同名函数,但是c++是支持同名函数的
两个命名空间域中的同名函数不叫函数重载
函数重载的注意事项:
#include<iostream>
using namespace std;void Swap(int* pa, int* pb)
{cout << "void Swap(int* pa, int* pb)" << endl;
}void Swap(double* pa, double* pb)
{cout << "void Swap(double* pa, double* pb)" << endl;
}int main()
{int a = 0, b = 1;double c = 0.1, d = 1.1;Swap(&a, &b);Swap(&c, &d);return 0;
}
看的是形参的类型,而不是形参的名字
不同的作用域可以定义同名的函数和变量
下面是三种不同的重载方式:
#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;
}// 2、参数个数不同
void f()
{cout << "f()" << endl;
}void f(int a)
{cout << "f(int a)" << endl;
}// 3、参数类型顺序不同
void f(int a, char b)
{cout << "f(int a,char b)" << endl;
}void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}int main()
{Add(10, 20);Add(10.1, 20.2);f();f(10);f(10, 'a');f('a', 10);return 0;
}
重点: 返回值是不能作为重载的条件的
void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}int main()
{f(1, 'a');f('a', 1);f('a', 'b');return 0;
}
这样是可以的,char可以隐式转换成int,int也可以隐式转换成char,所以上面的是可以的
2.C++支持函数重载的原理--名字修饰(name Mangling)
"Stack.cpp"#include"Stack.h"void StackInit(struct Stack* ps, int n)
{cout << "void StackInit(struct Stack* ps, int n)" << endl;
}void f(int a, char b)
{cout << "f(int a,char b)" << endl;
}void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}
"Stack.h"#pragma once
#include<iostream>
using namespace std;struct Stack
{
};void StackInit(struct Stack* ps, int n);
void f(int a, char b);
void f(char b, int a);
void f(int b, int a);
"test.cpp"#include"Stack.h"int main()
{struct Stack st;StackInit(&st, 10);f(1, 'a');f('b', 10);f(1, 1);return 0;
}
去符号表里面去找,找到了就是链接成功了,没找到,就链接失败了
修饰的函数名:修饰规则,在不同的编译器下,函数名的修饰规则不同
Linux下进行修饰会更加简洁一点
Linux下的c编译完之后,函数名就是这样的,所以c语言是不支持重载的
二.引用
1.引用的使用
int main()
{int a = 0;// 引用:b是a的别名int& b = a;int& c = a;int& d = b;++d;cout << &a << endl;cout << &b << endl;cout << &c << endl;cout << &d << endl;return 0;
}
在类型名后面就是引用,在我们的变量前面就是取地址
void Swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}
int main()
{int x = 0, y = 1;Swap(x, y);cout << x << ":" << y << endl;return 0;
}
这样就完成了交换了,可以用引用来代替指针进行操作
这块代码也是指针和引用的替换使用
typedef struct ListNode
{int val;struct ListNode* next;
}LTNode, *PNode;// typedef struct ListNode* PNode;//void ListPushBack(LTNode** phead, int x)
//void ListPushBack(LTNode*& phead, int x)
void ListPushBack(PNode& phead, int x)
{if (phead == NULL){// phead = newnode;}
}
2.引用的特性
1. 引用在定义时必须初始化
2. 一个变量可以有多个引用
3. 引用一旦引用一个实体,再不能引用其他实体
void TestRef()
{int a = 10;// int& ra; // 该条语句编译时会出错int& ra = a;int& rra = a;printf("%p %p %p\n", &a, &ra, &rra);
}
int main()
{int x = 0;int& y = x;//权限的放大//m是只读的//n变成我的别名,n的权限是可读可写的//权限不能放大,只能权限缩小或平移const int m = 0;int& n = m;return 0;
}
上面这个地方代码是错误的
int main()
{// 权限的平移int x = 0;int& y = x;// 权限的缩小,可以const int& z = x;//z++; // 不可以y++;// 权限的方法// m只读// n变成我的别名,n的权限是可读可写// 权限的放大,不可以const int m = 0;// int& n = m;const int& n = m;// 可以,不是权限的放大// m拷贝的给p,p的修改不影响mint p = m;// 权限的放大// p1可以修改 *p1不可以,const修饰是的*p1const int* p1 = &m;// p1++;// int* p2 = p1;const int* p2 = p1;// 权限的缩小int* p3 = &x;const int* p4 = p3;return 0;
}
权限的放大和缩小,只和&有关系