Here是相应的问题,我想知道的是,是否可以通过成员函数将全局函数引入重载决策?
我试过两种方式,但都不起作用:
void foo(double val) { cout << "double\n";}
class obj {
public:
using ::foo; // (1) compile error: using-declaration for non-member at class scope
void callFoo() {
using ::foo; // (2)will cause the global version always be called
foo(6.4);
foo(0);
}
private:
void foo(int val) {cout << "class member foo\n"; }
};
答案 0 :(得分:4)
我怀疑你可以根据类型让编译器调用一个或另一个。您当然可以使用本地包装函数,如下所示:
void callFoo() {
foo(6.4);
foo(0);
}
private:
void foo(double val) { ::foo(val); }
包装器函数应该很好地内联到任何内容,因此在使用优化进行编译时没有实际的开销。
或者不要将成员和全局函数称为同名,这会让生活变得更加容易!
答案 1 :(得分:1)
你不能这样做可能因为成员函数具有不同的签名,编译器可以看到它,
void foo(double)
VS
void obj::foo(int)
答案 2 :(得分:1)
您尝试做的是使用参数类型选择正确的重载,并将外部foo引入您的类或成员函数。
将它带入课堂很容易。您只需将另一个重载声明为转发到外部的类成员。
引入该函数是棘手的,但可以通过使用辅助函数来完成,例如您可以通过callFoo调用fooCaller( double )
和fooCaller( int )
。
如果您不想将这些内容暴露给外部用户,即在cpp文件中将它们隐藏起来,那么可以这样做但是比较棘手,因为您班级中的foo
是私有的。您必须让私有函数中的callFoo
函数作为成员函数传递,以“调用”int重载。
答案 3 :(得分:1)
这是普通的非限定名称查找,在§3.4.1[basic.lookup.unqual]中指定:
1在3.4.1中列出的所有情况下,搜索范围为a 按各自类别列出的顺序进行声明; 一旦找到名称的声明,名称查找就会结束。如果不 声明被发现,该程序是不正确的。
8对于类
X
的成员,在成员函数中使用的名称 body,在默认参数中,在 exception-specification 中,在 brace-or-equal-initializer 非静态数据成员(9.2),或者在X定义之外的类成员的定义中, 在成员的 declarator-id 之后,应在其中一个中声明 以下方式:
- 在使用它之前或在封闭块(6.3)或
中使用之前- 应该是类
X
的成员,或者是X
(10.2)的基类成员,或者- 如果
X
是类Y
(9.7)的嵌套类,则应为Y
的成员,或者应为Y
基类的成员(此查找适用 反过来到Y
的封闭类,从最里面开始 封闭类)或- 如果
X
是本地类(9.8)或是本地类的嵌套类,则在包含定义的块中定义类X
之前 班级X
,或- 如果
X
是名称空间N
的成员,或者是N
成员的类的嵌套类,或者是本地类或嵌套类 在使用之前,是N
成员的函数的本地类 名称,在名称空间N
或N
的一个名称空间中。
首先请注意,一旦找到声明,名称查找就会停止。因此,如果using ::foo;
中有callFoo()
,则foo
的查找将在此处结束,并且永远不会触及第二个项目符号点;如果您没有,查找foo
会在第二个项目符号点找到成员foo()
,而不会在其他地方搜索。指定非限定名称查找的方式意味着您将找到类成员或非类成员,但不会同时找到它们。
§13.1.1.1[over.call.func] / p3中也提到了这一点:
在不合格的函数调用中,名称不符合 - &gt;要么 。 运算符,具有 primary-expression 的更通用形式。该 在后面的函数调用的上下文中查找名称 函数调用中名称查找的常规规则(3.4)。功能 该查找找到的声明构成候选集 功能。由于名称查找规则,候选人集 功能包括(1)完全由非成员函数或(2) 完全是某些类
T
的成员函数。在情况(1)中,参数列表 与调用中的表达式列表相同。在案例(2)中, 参数列表是由增强的调用中的表达式列表 在限定函数中添加隐含对象参数 调用
类范围内的 using-declaration 必须命名基类成员(§7.3.3[namespace.udecl] / p3):
在用作成员声明的 using-declaration 中, nested-name-specifier 应命名要定义的类的基类。