函数重载细说
在C++语言中,同一范围内相同名称的不同声明称为重载,只有函数声明可以重载,对象或类型声明都不能重载。那是不是所有满足签名相同的函数就一定可以被重载呢?
一、函数重载适用范围
必须在同一范围(scope),比如同一命名空间或类中。不同命名空间或类中的同名函数不能称为函数重载。下面通过代码进行验证。
不同命名空间:
1 namespace A { 2 void Func(int a, int b) 3 { 4 5 } 6 7 int Func(int a, int b) // Compile Error, redefinition 8 { 9 10 } 11 } 12 13 namespace B { 14 void Func(int a, int b) 15 { 16 17 } 18 }
编译失败,提示命名空间A中的函数重定义了。但是命名空间B没有出现编译提示重定义。
不同类中:
1 class ClassA 2 { 3 public: 4 void Method() 5 { 6 7 } 8 9 int Method() // Compile Error, redefinition. 10 { 11 12 } 13 14 }; 15 16 class ClassB 17 { 18 void Method() 19 { 20 21 } 22 };
类似命名空间,提示ClassA范围函数重复定义,但是ClassB没有报错。
二、函数不能重载的情况
命名空间或全局空间范围:
1.仅仅函数返回类型不同,不可重载:
1 namespace A { 2 void Func(int a, int b) 3 { 4 } 5 6 int Func(int a, int b) 7 { 8 return a + b; 9 } 10 }
2.参数是指针类型和数组类型且相同,不可重载:
1 namespace A { 2 void Func(int* b) 3 { 4 } 5 6 void Func(int arr[]) 7 { 8 9 } 10 }
因为编译器会将数组类型的转换为指针类型处理,所以不能作为函数重载。
3.参数指向同一函数地址,不可重载:
1 namespace A { 2 void Func(int()) 3 {} 4 5 void Func(int(*)()) 6 {} 7 }
4.参数以值传递的方式并被const和volatile修饰,不可重载:
1 namespace A { 2 void Func(const int x) // 值传递 3 {} 4 5 void Func(volatile int x) // 值传递 6 {} 7 }
如果是引用传递或指针传递,const和volatile,可以被重载:
1 namespace A { 2 void Func(const int* ptr) 3 {} 4 5 void Func(int* const ptr) 6 {} 7 8 /*void Func(const int* const ptr) // void Func(const int* ptr) Redefinition 9 {}*/ 10 11 void Func(volatile int* ptr) 12 {} 13 14 void Func(int& value) 15 {} 16 17 void Func(const int& value) 18 {} 19 20 //void Func(int& const value) // void Func(const int& value) Redefinition 21 //{} 22 23 void Func(volatile int& value) 24 {} 25 }
5.仅仅是默认参数个数不同,不可重载:
1 namespace A { 2 void Func(int a, int b) 3 {} 4 5 void Func(int a, int b = 10) 6 {} 7 8 void Func(int a = 10, int b = 10) 9 {} 10 }
类范围,除了上面几种情况外,还涉及到成员函数是静态还是非静态,是const还是非const的:
1.成员函数名称和参数相同,不管是静态还是非静态成员函数,不可重载:
1 class ClassA 2 { 3 public: 4 static void Method() 5 {} 6 7 void Method() 8 { 9 } 10 };
2.成员函数名称和参数相同,不管是否被const或volatile修饰,不可重载:
1 class ClassA 2 { 3 public: 4 static void Method() 5 {} 6 7 void Method() 8 {} 9 10 void Method() const 11 {} 12 13 void Method() volatile 14 {} 15 };
三、总结
谈论函数重载,必须是同一范围内,函数签名相同,参数个数或类型不同。同学们不光要知道函数重载的一般形式,也要知道函数不可重载的情况,方便日后编写代码或看其他人编写代码的时候能知其然。