在C ++中,返回类型是否被认为是函数签名的一部分?只修改了返回类型,不允许重载。
答案 0 :(得分:81)
普通函数的签名中不包含返回类型。
( note :我已经重写了这个答案,以下评论不适用于此修订版 - 有关详细信息,请参阅编辑历史记录。)
然而,标准中关于函数和函数声明的问题很复杂。必须考虑两个层次:
所谓的函数声明可以声明一个函数实体或一个模板实体。如果声明了一个函数实体,那么您要么必须使用函数模板的显式特化(指定所有参数),要么使用普通函数的声明。如果声明了模板实体,那么您将声明主函数模板,或者未指定某些参数的显式特化。 (这与“对象声明”和对象或引用的关系非常相似:前者可以声明对象或引用。因此对象声明可能不一定声明对象!)。
标准定义了一个函数的签名,以便在1.3.10
包含以下内容:
其参数的类型,如果函数是类成员,则函数本身的cv限定符(如果有)以及声明成员函数的类。函数模板特化的签名包括其模板参数的类型。 (14.5.5.1)
它缺少此定义中的返回类型,其中是函数模板特化的签名的一部分(即声明函数是模板特化的函数声明),如指向的那样out 14.5.5.1
(最近的C ++ 0x工作文件修正了已经提到1.3.10
中的返回类型):
函数模板特化的签名包括函数模板的签名和实际模板参数的签名(无论是明确指定还是推导)。
函数模板的签名包括其函数签名,返回类型和模板参数列表。
因此,当我们询问函数的签名时,我们必须给出两个答案:
但请注意,返回类型(无论如何) 是函数类型的重要部分。也就是说,以下内容无效:
void f();
int (*pf)() = &f; // different types!
主要编译器目前拒绝以下代码:
int f();
double f(); // invalid
但接受以下代码:
template<typename T> int f();
template<typename T> double f(); // invalid?
但是,标准会禁止仅在返回类型中有所不同的函数声明(在定义重载何时有效时,何时不存在)。但是,它没有精确定义“只有返回类型不同”的含义。
标准段落引用:
13.1
7/2
和7/5
14.5.5.1
作为参考,以下是1.3.11
中最新的C ++ 0x草案n3000关于“签名”的内容,它对不同类型实体的覆盖范围要完整得多:
函数的名称和参数类型列表(8.3.5),以及它所属的类或命名空间。如果函数或函数模板是类成员,则其签名还包括函数或函数模板本身的cv-quali firs(如果有)和ref-quali fi er(如果有)。函数模板的签名还包括其返回类型和模板参数列表。函数模板特化的签名包括作为特化的模板的签名及其模板参数(无论是明确指定还是推导)。 [注意:签名用作名称修改和链接的基础。 - 结束说明]
答案 1 :(得分:10)
这取决于函数是否是函数模板。
在 C ++模板 - 完整指南中,Jusuttis提供了与C ++标准中给出的不同的定义,但具有相同的结果:
我们将函数的签名定义为以下信息:
const
,volatile
或const volatile
限定正如 litb 建议的那样,值得澄清为什么返回类型是模板函数签名的一部分。
如果,函数可以在程序中共存 他们有不同的签名。
。也就是说,如果返回类型是模板参数:
template <typename T>
T foo(int a)
{return T();}
可以实例化两个仅在返回类型上不同的函数:
foo<int>(0);
foo<char>(0);
不仅如此:正如 litb 正确报告的那样,也可以重载两个模板函数,这些函数仅在返回类型上有所不同,即使返回类型不是从属名称也是如此。这是他的例子:
template<class T> int foo(T)
{}
template<class T> bool foo(T)
{}
// at the instantiation point it is necessary to specify the cast
// in order not to face ambiguous overload
((int(*)(char))foo<char>)('a');
答案 2 :(得分:2)
它们足以成为类型的一部分,您可以根据仅由返回类型不同的函数指针类型重载函数:
int IntFunc() { return 0; }
char CharFunc() { return 0; }
void FuncFunc(int(*func)()) { cout << "int\n"; }
void FuncFunc(char(*func)()) { cout << "char\n"; }
int main()
{
FuncFunc(&IntFunc); // calls void FuncFunc(int_func func)
FuncFunc(&CharFunc); // calls void FuncFunc(char_func func)
}