通过重复对象名称来调用静态方法?
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
。
由于名称注入,N::A
在B
的构造函数中可用,而没有限定。它还隐藏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]/2
,foo::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
不使用注入的名称。以上是关于通过重复对象名称来调用静态方法?的主要内容,如果未能解决你的问题,请参考以下文章