const能否用于函数重载?
const能否用于函数重载?
因为const关键字在函数签名中可以以不同的方式出现,所以分几种不同的情况:
const修饰形参,形参为非引用型
//test.cpp
#include <iostream>
void func(int a)
{
std::cout << "Func signature:" << "func(int a)" << std::endl;
}
void func(const int a)
{
std::cout << "Func signature:" << "func(int a)" << std::endl;
}
int main(int argc, char const *argv[])
{
int a = 42;
const int b = 10;
func(a);
func(b);
return 0;
}
//g++ -std=c++11 test.cpp -o test
编译无法通过,提示redefinition of ‘void func(int)’
错误。所以当形参为非引用类型时,在编译器看来,有无const修饰形参都是一样的,两者没有任何区别,是同一个函数。所以此时const不能作为函数重载的依据。
const修饰形参,形参为引用型
//test.cpp
#include <iostream>
void func(int& a)
{
std::cout << "Func signature:" << "func(int& a)" << std::endl;
}
void func(const int& a)
{
std::cout << "Func signature:" << "func(const int& a)" << std::endl;
}
int main(int argc, char const *argv[])
{
int a = 42;
const int b = 10;
func(a);
func(b);
return 0;
}
//g++ -std=c++11 test.cpp -o test
编译通过,执行test
文件:
./test
Func signature:func(int& a)
Func signature:func(const int& a)
可以清楚的看到,当实参类型是非const的时,执行的是非const修饰形参的函数版本,而当实参类型是const的时,执行的函数是const修饰形参的函数版本。所以此时const可以作为函数重载的依据。
const修饰形参,形参为指针型
指针和引用非常类似,
//test.cpp
#include <iostream>
void func(int* a)
{
std::cout << "Func signature:" << "func(int* a)" << std::endl;
}
void func(const int* a)
{
std::cout << "Func signature:" << "func(const int* a)" << std::endl;
}
int main(int argc, char const *argv[])
{
int a = 42;
const int b = 10;
func(&a);
func(&b);
return 0;
}
//g++ -std=c++11 test.cpp -o test
编译通过,执行test
文件:
./test
Func signature:func(int* a)
Func signature:func(const int* a)
但是指针情况更为复杂,因为指针分为常量指针(指针为常量,不可修改,但是指向的内容可以修改)和指向常量的指针(指针可以修改,但是不同通过指针更改指针指向的对象),
//test.cpp
#include <iostream>
void func(int* a)
{
std::cout << "Func signature:" << "func(int* a)" << std::endl;
}
void func(int* const a)
{
std::cout << "Func signature:" << "func(int* const a)" << std::endl;
}
int main(int argc, char const *argv[])
{
int a = 42;
const int b = 10;
int * const c = new int(0);
func(&a);
func(c);
delete c;
return 0;
}
//g++ -std=c++11 test.cpp -o test
编译无法通过,原因和第一种情况类似,不能重定义函数void func(int*)
,也就是说函数签名func(int* const a)
中的const被编译器忽略了。
结合第一种情况我们不难得出,在编译过程中,编译器忽略了顶层const,而底层const被保留了。所以底层const可以作为重载的依据,而顶层const却不能。
const修饰的常量成员函数
//test2.cpp
#include <iostream>
class Demo{
public:
void func(int a){
std::cout << "Func signature:" << "Demo::func(int a)" << std::endl;
}
void func(int a) const{
std::cout << "Func signature:" << "Demo::func(int a) const" << std::endl;
}
};
int main(int argc, char const *argv[])
{
Demo demo;
const Demo cst_demo;
int a = 42;
demo.func(a);
cst_demo.func(a);
return 0;
}
//g++ test2.cpp -std=c++11 -o test
执行结果如下:
./test
Func signature:Demo::func(int a)
Func signature:Demo::func(int a) const
可以看出,可以根据是否在类的成员函数后跟上const来重载成员函数。但是这个重载在形式上并非通过实参是否是const来判断调用函数,而是通过类的实例是否是const的来匹配成员函数。(其实实际上也是,因为func(int a)
函数真实的签名是func(Demo&,int)
,而func(int a) const
的真实签名是func(const Demo&,int)
,本文不再深究,有兴趣的同学可以研究一下类的成员函数的真实签名。)
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!