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

时间:2014-09-16 07:58:17

标签: c++ overloading

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"; }
};

4 个答案:

答案 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成员的函数的本地类   名称,在名称空间NN的一个名称空间中。
  •   

首先请注意,一旦找到声明,名称查找就会停止。因此,如果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 应命名要定义的类的基类。