是否可以通过成员函数将全局函数引入重载决策?

son*_*yao 6 c++ overloading

是相应的问题,我想知道的是,是否有可能通过成员函数将全局函数引入重载决策?

我试过两种方式,但都不起作用:

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"; }
};
Run Code Online (Sandbox Code Playgroud)

Mat*_*son 5

我怀疑您能否让编译器根据类型调用一个或另一个。您当然可以使用本地包装函数,如下所示:

  void callFoo() { 
    foo(6.4); 
    foo(0); 
  }
private:
  void foo(double val) { ::foo(val); }
Run Code Online (Sandbox Code Playgroud)

包装器函数应该很好地内联成空,因此在优化编译时没有实际开销。

或者不要将成员和全局函数称为同名,这会让生活变得更轻松!


T.C*_*.C. 2

这是普通的旧的非限定名称查找,在 \xc2\xa73.4.1 [basic.lookup.unqual] 中指定:

\n\n
\n

1 在 3.4.1 列出的所有情况下,将按照每个相应类别中列出的顺序在范围中搜索声明;一旦找到名称的声明,名称查找就会结束。如果未找到\n 声明,则程序格式错误。

\n\n

8 对于类的成员X,在成员函数体、默认参数、异常规范、 非静态数据成员的大括号或等于初始化器中使用的名称 (9.2 ),或者在 X 定义之外的类成员定义中,\n 位于 member\xe2\x80\x99s declarator-id之后之后,应通过\n 以下方式之一进行声明:

\n\n
    \n
  • 在使用它的块或封闭块(6.3)中使用之前,或
  • \n
  • 应是 (10.2) 类的成员X或基类的成员X,或
  • \n
  • 如果X是类Y(9.7) 的嵌套类,则应是 的成员Y,或者应是 的基类的成员Y(此查找依次适用于Y\xe2\x80\x99s 封闭类,从最里面的\ n 封闭类​​),或者
  • \n
  • ifX是本地类 (9.8) 或者是本地类的嵌套类,位于X包含 class 定义的块中的 class 定义\n之前X,或者
  • \n
  • ifX是 命名空间 的成员N,或者是 的成员的类的嵌套类N,或者是本地类或\n函数的本地类中的嵌套类,而该函数是 的成员N,在使用之前\n命名空间中N或 \xe2\x80\x99s 封闭命名空间之一中的名称N
  • \n
\n
\n\n

首先请注意,一旦找到声明,名称查找就会停止。因此,如果您有using ::foo;in callFoo(),则查找foo将在那里结束,并且永远不会触及第二个要点;如果没有,查找将在第二个项目符号点foo找到该成员,而不会在其他地方搜索。foo()指定非限定名称查找的方式意味着您将找到类成员或非类成员,但绝不会两者都找到。

\n\n

\xc2\xa713.1.1.1 [over.call.func]/p3 中也注意到了这一点:

\n\n
\n

在非限定函数调用中,名称不由 -> 或 .\n 运算符限定,并且具有更通用的primary-expression形式。按照函数调用中名称查找的正常规则 (3.4) 在函数调用的上下文中查找名称。该查找找到的函数声明构成了候选函数集。由于名称查找的规则,候选函数集由 (1) 完全非成员函数或 (2) 完全由某个类的成员函数组成T。在情况 (1) 中,参数列表\n 与调用中的表达式列表相同。在情况 (2) 中,参数列表是调用中的表达式列表,通过在限定函数调用中添加隐含对象参数来扩充。

\n
\n\n
\n\n

类范围内的using声明必须命名基类成员 (\xc2\xa77.3.3 [namespace.udecl]/p3):

\n\n
\n

在用作成员声明的using 声明中,嵌套 名称说明符应命名所定义的类的基类。

\n
\n