不懂顶层const和非顶层const的区别的先查看我的这篇博客:https://blog.youkuaiyun.com/obsorb_knowledge/article/details/100926991
介绍const函数重载的问题前,先介绍一下下面代码:
#include<iostream>
using namespace std;
int ans = 42;
void fun(int *tt)
{
tt = &ans;
}
int main()
{
int i = 100;
fun(&i);
cout << i <<endl; // 输入 i == 100;
}
上面程序输出i == 100;在调用函数内部改变指针指向,是不影响实参的。
#include<iostream>
using namespace std;
int ans = 42;
void fun(int *tt)
{
*tt = 42;
}
int main()
{
int i = 100;
fun(&i);
cout << i <<endl; // 输入 i == 42;
}
上面程序输出i == 42;在调用函数内部改变指针指向的内容,是影响实参的。
#include<iostream>
using namespace std;
int ans = 42;
void fun(int *tt)
{
tt = &ans;
*tt = 50;
}
int main()
{
int i = 100;
fun(&i);
cout << i << " " << ans <<endl; // 输入 i == 100, ans == 50;
}
上面程序 i == 100,ans == 50;
下面介绍,const的重载。
(1) C++ 11 中说,一个拥有顶层的const的形参无法和一个没有拥有顶层的const的形参区别开来,也是说,下面声明是等价的,不可以实现函数重载
int C_fun(int *p);
{
return 0;
}
int C_fun(int *const p); //重复定义
{
return 1;
}
int fun(int p);
int fun(const int p); //重复声明
C++ 只说了这样是重复定义,但是没有说为什么。
① 顶层的const 不可以改变指向,而形参指针在调用函数内部,改变指针指向,是改变的形参的指向,对实参没什么影响。
② 而顶层的const 可以改变指向的内容,而形参指针在调用函数内部,可以改变指向内容,同时也改变了实参的指针指向的内容。
调用函数中的形参 和 顶层const的作用重叠,所以这重复定义。
(2)底层的const形参和普通形参是可以区别开的,可以实现重载。 C++ 11 上说则通过区分其指向的是常量对象还是非常量对象可以实现重载。如下:
int C_fun(const int *p) //底层 const
{
return 2;
}
int C_fun(int *p)
{
return 1;
}
调用 int i = 100; C_fun (&i);首先可以调用普通形参的函数(第二函数),当把第二个函数去掉时,它也可以调用第一函数 int C_fun(const int *p) ,因为下面在定义时都可以实现,变量指针可以初始化(定义)常量指针,但是const底层常量指针不能赋予变量指针
int i = 42;
int *pp = &i;
const int *FD_pp = pp; // 非顶层const 反过来 pp = FD_pp;这样不行。
int *const D_pp = pp; // 顶层const
那么为什么他们两个函数可以实现重载呢?
这时候就要分析形参的特性 和 非顶层const 的特性了
① 非顶层的const,本身就能改变指针指向,但是在形参指针在调用函数内部改变了指针指向,却对实参不起作用。
② 但是它不可以改变指针指向数的值,而不管是顶层const指针,还是普通指针,都可以改变指针指向内容的值,一旦改变就会就会影响实参。
可以看到作用互斥。可以重载。
注意如下:这样调用就是常量指针了,对实参不能起任何影响
#include<iostream>
using namespace std;
int ans = 42;
//这样引用就是常量引用了,即不可以改变实参的指针的指向,也不可以改变实参指针指向的内容
void fun(const int *tt)
{
tt = &ans; // 改变指向对实参没影响
*tt = 50; // 改变指向的内容,编译器编不过去。
}
int main()
{
int i = 100;
fun(&i);
}
再看一下这个:
#include<iostream>
using namespace std;
void fun(int *tt)
{
return 0;
}
int main()
{
const int i = 100;
// int *k = &i; 常量地址不能赋予变量指针
const int *p = &i;
// fun(p); 底层const 常量指针,也不能赋值变量指针。
int tt = 100;
int *const p = &tt;
int *k = p; // 顶层 const常量指针,可以赋予变量指针。
}
上面的特征应该和const int *p 和 int *const p;
const int *p 这里const 修饰的是int,而int定义的是一个整值,所以这里 p为指向常量的指针。
int *const a 这里const修饰的是 a ,a代表的是一个指针地址,a就是常量指针。
最后注意一点:
(1)编译器会找到一个与实参最佳匹配的函数,并生成调用函数的代码。
(2)找不到任何一个函数与调用的实参匹配,此时编译器发出无匹配的错误信息。
(3)有多于一个函数可以匹配,但是每一个都不是明显的最佳选择时,此时也将发生错误,称为二义性调用。
欢迎指正。。。