在C ++中,返回类型是否被视为函数签名的一部分?并且仅修改返回类型就不允许重载。
Answers:
普通函数的签名中不包含返回类型。
(注意:我已经重写了此答案,并且以下注释不适用于此修订版-有关详细信息,请参见编辑历史)。
但是,标准中有关函数和函数声明的问题很复杂。必须考虑两层:
所谓的功能声明可以声明功能实体或模板实体。如果声明了一个功能实体,那么您要么必须要明确定义功能模板(指定所有参数),要么要声明一个普通函数。如果声明了模板实体,那么您将声明一个主函数模板,或者未指定某些参数的显式专门化。(这与“对象声明”与对象或引用的关系非常相似:前者可以声明对象或引用。因此,对象声明不一定必须声明对象!)。
该标准在以下位置定义了功能的签名1.3.10
:
其参数的类型,如果函数是类成员,则为函数本身以及声明该成员函数的类的cv限定词(如果有)。功能模板特化的签名包括其模板参数的类型。(14.5.5.1)
正如(最近的C ++ 0x工作论文所指出的),此定义中缺少返回类型,该类型是函数模板特化(即声明函数的功能声明,它是模板的特化)的签名的一部分。14.5.5.1
修复了已经提到返回类型的问题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
作为参考,这是最新的C ++ 0x草案n3000关于中的“签名”的说法1.3.11
,它在涵盖不同类型的实体方面更加完整:
函数的名称和参数类型列表(8.3.5),以及该函数所属的类或名称空间。如果功能或功能模板是类成员,则其签名还应包括功能或功能模板本身上的cv限定符(如果有)和ref限定符(如果有)。功能模板的签名还包括其返回类型和模板参数列表。功能模板特化的签名包括为其特化的模板的签名及其模板自变量(无论是明确指定还是推导)。[注意:签名用作名称处理和链接的基础。—尾注]
这取决于功能是否为功能模板。
在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');
它们是该类型的一部分,您可以根据仅返回类型不同的函数指针类型来重载函数:
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)
}