首先要明确的概念:const&volatile关键字,可以用于实现函数重载。
然而事情并不是像这句话看起来这么简单。
首先,对于采用传值方式的参数,const &volatile 关键字无法区分参数类型,不具备实现函数重载的能力。
如:
void func (int a );
void func (const int a);
这两个函数声明会被编译器视为重复声明。
其次,对于采用指针和引用这两种传递方式的参数,const &volatile关键字此时可以区分参数类型,可以实现函数重载。
如
void func( int * a);
void func( const int * a);
void func( int & a);
void func( const int & a);
上述4个函数会被视为4个不同版本的重载。
最后,const & volatile关键字在后置修饰类成员函数时,同样具备实现函数重载的能力。
如
class A
{
void sig (int a) const;
void sig (int a ) ;
};
class A中的sig函数有两个版本,对于non-const的A类型对象,会调用non-const版本的sig(),而对于const的A类型对象,则会调用const版本的sig()。
这一特性很容易理解:我们都知道对于非静态类成员函数,在其被调用时由编译器隐式的传入this 指针,对于non-const对象调用sig()时,所传入的this指针的类型为 A *,而对于const对象调用sig()时,所传入的this指针的类型为 const A *,编译器就根据this 指针类型的不同来完成函数重载。
实际上,对下面的测试程序进行反汇编,也可以看出编译器为两个版本的sig()所生成的用于链接的函数名是不同的——我用g++编译后,non-const版本和const版本的sig()的名称分别是"_ZN1A3sigEi"和“_ZNK1A3sigEi”
以下是测试代码
#include <iostream>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
using namespace std;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
class A
{
public:
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
A(){ count=0;}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
void sig(int a ) const { cout<<"const version--count="<<count<<endl;}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
void sig(int a ) { count=a; cout<<"non-const version--count="<<count<<endl;}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private:
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
int count;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
};
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int main ( int argc,char * argv[])
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
/*const*/ A tmp;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
tmp.sig(1);
tmp.sig(2);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return 1;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
然而事情并不是像这句话看起来这么简单。
首先,对于采用传值方式的参数,const &volatile 关键字无法区分参数类型,不具备实现函数重载的能力。
如:
void func (int a );
void func (const int a);
这两个函数声明会被编译器视为重复声明。
其次,对于采用指针和引用这两种传递方式的参数,const &volatile关键字此时可以区分参数类型,可以实现函数重载。
如
void func( int * a);
void func( const int * a);
void func( int & a);
void func( const int & a);
上述4个函数会被视为4个不同版本的重载。
最后,const & volatile关键字在后置修饰类成员函数时,同样具备实现函数重载的能力。
如
class A
{
void sig (int a) const;
void sig (int a ) ;
};
class A中的sig函数有两个版本,对于non-const的A类型对象,会调用non-const版本的sig(),而对于const的A类型对象,则会调用const版本的sig()。
这一特性很容易理解:我们都知道对于非静态类成员函数,在其被调用时由编译器隐式的传入this 指针,对于non-const对象调用sig()时,所传入的this指针的类型为 A *,而对于const对象调用sig()时,所传入的this指针的类型为 const A *,编译器就根据this 指针类型的不同来完成函数重载。
实际上,对下面的测试程序进行反汇编,也可以看出编译器为两个版本的sig()所生成的用于链接的函数名是不同的——我用g++编译后,non-const版本和const版本的sig()的名称分别是"_ZN1A3sigEi"和“_ZNK1A3sigEi”
以下是测试代码
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)