通過重復對象名稱來調用靜態方法?

[英]Calling a static method by repeating the object name?


I have a singleton:

我有一個單身人士:

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

When re-arranging some code I ended up with this statement "by error":

在重新安排一些代碼時,我最終得到了“錯誤”這句話:

foo::foo::instance()

But this is deemed correct by my compiler (gcc 4.7). In fact, even foo::foo::foo::instance() compiles. Why?

但是我的編譯器認為這是正確的(gcc 4.7)。實際上,甚至foo :: foo :: foo :: instance()也會編譯。為什么?

3 个解决方案

#1


44  

It is due to "injected-name" — which means if foo is a class-name, and the same name "foo" is also injected into the class-scope which is why your code works. It is 100% Standard-conformant.

這是由於“注入名稱” - 這意味着如果foo是一個類名,並且同樣名稱“foo”也被注入到類范圍中,這就是你的代碼工作的原因。它符合標准100%。

Here is one interesting example which shows the benefits of this feature:

這是一個有趣的例子,展示了這個功能的好處:

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

What should a.f() call? What is the type of a? Is it M::A or N::A? The answer is, N::A, not M::A.

a.f()應該叫什么?什么類型的?它是M :: A還是N :: A?答案是,N :: A,而不是M :: A。

It is because of name-injection, N::A is available inside the constructor of B without qualification. It also hides M::A, which remains outside the scope of B. If you want to use M::A, then you've to write M::A (or better ::M::A).

這是因為名稱注入,N :: A在B的構造函數內可用而沒有資格。它也隱藏了M :: A,它仍然在B的范圍之外。如果你想使用M :: A,那么你要寫M :: A(或更好:: M :: A)。

#2


21  

Because of [class]/2:

因為[class] / 2:

A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.

在看到類名后立即將類名插入到作用域中。類名也插入到類本身的范圍內;這被稱為注入類名。

So foo::foo is an injected class name, denoting foo itself.

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


Actually it's a bit more complicated: according to [class.qual]/2, foo::foo alone denotes a constructor of foo. In order to denote a class, it should either be preceded by struct (making it elaborated-type-specifier), or followed by :: (making it a nested-name-specifier - this is your case), or be a base-specifier (for example struct bar : foo::foo {};).

實際上它有點復雜:根據[class.qual] / 2,foo :: foo單獨表示foo的構造函數。為了表示一個類,它應該在struct之前(使其成為詳細的類型說明符),或者后跟::(使它成為嵌套名稱說明符 - 這是你的情況),或者是一個基礎 - 說明符(例如struct bar:foo :: foo {};)。

#3


11  

As stated in the other answers, the reason is name injection. To me, the main use case would be the following

如其他答案中所述,原因是名稱注入。對我來說,主要用例如下

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

struct D : B1, B2 { }

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

In main the call to f is ambiguous and won't compile. The way to be specific is a qualified call, ie

在main中,對f的調用是模糊的,不會編譯。具體的方式是合格的呼叫,即

obj.B1::f(); 

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2014/11/26/725bd230426a71ba16d14395d3e6de64.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com