- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这是 this 的后续题。
#include <iostream>
struct type1 {};
struct type2 {};
void foo(type1 x)
{
std::cout << "foo(type1)" << std::endl;
}
template<typename T>
void bar() {
foo(T());
}
int main()
{
bar<type1>();
bar<type2>();
return 0;
}
void foo(type2 x)
{
std::cout << "foo(type2)" << std::endl;
}
在上面的代码中foo(type2)
在 bar<type2>
的实例化时不可见在 main
.然而代码编译并产生以下输出:
foo(type1)
foo(type2)
编译器如何知道 foo(type2)
实例化时可用 bar<type2>
在 main
?
编辑:我试图更多地了解模板实例化过程中的重载解析是如何工作的。考虑下面的代码:
#include <iostream>
struct type1 {};
struct type2 {};
struct type3 {
operator type2() { return type2(); }
};
void foo(type1 x)
{
std::cout << "foo(type1)" << std::endl;
}
void foo(type2 x)
{
std::cout << "foo(type2)" << std::endl;
}
int main()
{
foo(type3());
return 0;
}
void foo(type3 x)
{
std::cout << "foo(type3)" << std::endl;
}
输出是
foo(type2)
即使是更接近的比赛foo(type3)
有空,电话foo(type3())
解析为 foo(type2)
因为在那之前,这是唯一被编译器解析过的候选者。现在考虑以下代码:
#include <iostream>
struct type1 {};
struct type2 {};
struct type3 {
operator type2() { return type2(); }
};
void foo(type2 x)
{
std::cout << "foo(type2)" << std::endl;
}
template<typename T>
void bar() {
foo(T());
}
int main()
{
bar<type3>();
return 0;
}
void foo(type3 x)
{
std::cout << "foo(type3)" << std::endl;
}
输出是
foo(type3)
也就是调用点bar<type3>()
, 即使只有 foo(type2)
可见,编译器仍然选择 foo(type3)
稍后出现,因为这是更接近的匹配。
最佳答案
任何没有定义的符号都将在链接过程中被替换,因为函数 foo(type2)
可以在另一个文件中提供。
编译器会在整个过程结束时说出所需的函数是否已定义,此时无法应用进一步的替换。
为了阐明理解,您必须了解编译(例如,一个普通的 C 程序)所需的步骤:
首先,展开代码中的所有宏;
然后根据语言语法验证您的代码,以便将其转换为汇编语言——编译过程本身;在此步骤中,找到的每个没有定义的符号都会在表中用条目 (symbol, definition)
进行注释, 稍后将完成,以便正确构建您的程序;
接下来,您编译成汇编的代码将被转换为机器语言,即创建对象;
最后,您需要链接您已经可执行的对象,以解决对符号定义的任何依赖;最后一步检查您的对象是否有 undefined symbol ,添加来自其他模块或库的定义,从而完成程序。
如果任何符号没有正确“链接”到它的定义,编译器将指出程序中的错误——经典的 undefined reference to...
.
考虑到您发布的代码,该过程将一直执行到它到达编译器为止。编译器会遍历代码,注意 type1
的定义, type2
, foo(type1 x)
, 和 bar<T>()
.
struct type1 {};
struct type2 {};
当它到达 main 时,它会找到对 bar<type1>();
的调用, 并会调用 foo(type1())
,这是已知的,可以正确使用。
void foo(type1 x) {
std::cout << "foo(type1)" << std::endl;
}
template<typename T>
void bar() {
foo(T());
}
int main() {
bar<type1>();
bar<type2>();
return 0;
}
一旦到达下一个电话,bar<type2>();
, 它会尝试调用 foo(type2())
, 但没有这样的定义可供使用,因此它将此调用关联为未知符号,必须在以后的过程中用定义替换。
编译器运行完main
之后,它达到了一个新的定义,这正是正在创建的“翻译表”上缺少定义的定义。
void foo(type2 x) {
std::cout << "foo(type2)" << std::endl;
}
因此,在下一步中,编译能够用其各自的定义替换符号,并且程序可以正确编译。
问候!
关于c++ - 重载解析解析为一个尚不可见的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13485132/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!