顶层const和非顶层const和函数重载的问题

本文深入解析C++中const的使用,包括顶层const与底层const的区别,以及它们如何影响函数重载。通过实例说明const如何作用于指针及引用,解释编译器如何处理const修饰符,帮助理解函数重载机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不懂顶层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)有多于一个函数可以匹配,但是每一个都不是明显的最佳选择时,此时也将发生错误,称为二义性调用。

欢迎指正。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值