通过重复对象名称来调用静态方法?

Posted

技术标签:

【中文标题】通过重复对象名称来调用静态方法?【英文标题】:Calling a static method by repeating the object name? 【发布时间】:2014-11-26 15:07:44 【问题描述】:

我有一个单身人士:

struct foo 
  static foo& instance() 
    static foo f;
    return f;
  
;

在重新安排一些代码时,我“错误地”得到了这个语句:

foo::foo::instance()

但是我的编译器(gcc 4.7)认为这是正确的。事实上,即使foo::foo::foo::instance() 也可以编译。为什么?

【问题讨论】:

【参考方案1】:

这是由于“injected-name”——这意味着如果foo 是一个类名,并且同名“foo”也被注入到类范围中,这就是你的代码工作的原因。它 100% 符合标准。

这是一个有趣的例子,展示了这个功能的好处:

namespace N

   //define a class here
   struct A 
    
       void f()  std::cout << "N::A" << std::endl; 
   ;


namespace M

   //define another class with same name!
   struct A 
    
       void f()  std::cout << "M::A" << std::endl; 
   ;

   struct B : N::A  //NOTE : deriving from N::A
   
         B()
         
            A a;
            a.f(); //what should it print?
         
   ;

a.f() 应该调用什么? a 的类型是什么?是M::A 还是N::A?答案是N::A,而不是M::A

Online Demo

由于名称注入,N::AB 的构造函数中可用,而没有限定。它还隐藏M::A,它仍然在B 的范围之外。如果你想使用M::A,那么你必须写M::A(或者更好的::M::A)。

【讨论】:

【参考方案2】:

因为[class]/2

class-name 被插入到在看到 class-name 之后立即声明它的范围内。 class-name 也被插入到类本身的范围内;这被称为 injected-class-name

所以foo::foo 是一个注入的类名,表示foo 本身。


其实有点复杂:根据[class.qual]/2foo::foo单独表示foo的构造函数。为了表示一个类,它应该在前面加上struct(使其详细说明类型说明符),或者后跟::(使其成为nested-name-说明符 - 这是你的情况),或者是一个base-specifier(例如struct bar : foo::foo ;)。

【讨论】:

【参考方案3】:

如其他答案所述,原因是名称注入。对我来说,主要用例如下

struct B1  void f() ;
struct B2  void f() ;

struct D : B1, B2  

int main() 
    D obj; 
    obj.f(); 

main 中,对f 的调用不明确,无法编译。具体的方法是一个合格的调用,即

obj.B1::f(); 

【讨论】:

obj.B1::f 不使用注入的名称。

以上是关于通过重复对象名称来调用静态方法?的主要内容,如果未能解决你的问题,请参考以下文章

c# 有调用一个类的静态方法,是不是执行这个类的构造函数

Spring(十三):使用工厂方法来配置Bean的两种方式(静态工厂方法&实例工厂方法)

1.7Oob 静态变量静态方法

spring中静态类调用非静态对象的方法

通过工厂方法配置Bean

什么是静态方法?