关于c ++:为什么要调用静态成员函数。

Why is calling a static member function with . or -> syntax legal?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
C++ Static member method call on class instance

今天,我发现我有很长一段时间(我的意思是说,长达二十年),认为C++中的非法行为实际上是合法的。也就是说,调用一个静态成员函数,就好像它属于一个单独的对象一样。例如:

1
2
3
4
5
6
7
8
9
10
struct Foo
{
    static void bar() { cout <<"Whatever."; }
};

void caller()
{
    Foo foo;
    foo.bar();    // Legal -- what?
}

我通常看到静态成员函数被严格地用"范围解析语法"调用,因此:

1
Foo::bar();

这是有意义的,因为静态成员函数与类的任何特定实例都没有关联,因此我们不希望在语法上将特定实例"附加"到函数调用。

然而,今天我发现GCC4.2、GCC4.7.1和CLANG 3.1(作为编译器的随机抽样)接受以前的语法,以及:

1
2
Foo* foo = new Foo;
foo->bar();

在我的特殊情况下,这个表达式的合法性导致了一个运行时错误,这使我确信这个语法的特殊性不仅仅是学术上的兴趣,它还有实际的后果。

为什么C++允许静态成员函数被调用,就好像它们是单个对象的直接成员,也就是说,使用。或者->附加到对象实例的语法?


在C++第288页的设计和演进中,Bjarne Stroustrup提到在静态成员函数之前的日子里,程序员使用像((X*)0)->f()那样的HAKS来调用不需要对象的成员函数。我的猜测是,当静态成员函数被添加到语言中时,允许通过->进行访问,这样具有类似代码的程序员就可以将f更改为static,而不必搜索和更改它的每一种使用。


大概是这样,您可以在不知道某个类的类型但编译器知道的地方调用它。

假设我有很多类,每个类都有一个返回类名的静态成员:

1
2
3
4
5
6
7
8
9
class Foo
{
    static const char* ClassName() { return"Foo"; }
};

class Bar
{
    static const char* ClassName() { return"Bar"; }
};

然后在我的代码中,我可以做如下的事情:

1
2
3
4
Foo foo;

printf("This is a %s
"
, foo.ClassName() );

不用担心随时知道我的物品的种类。例如,在编写模板时,这将非常方便。


从C++(PDF)的演变,第8节。静态成员函数:

...It was also observed that nonportable code, such as

1
    ((x*)0)->f();

was used to simulate static member functions.

所以我的猜测是(基于几乎所有其他奇怪的语法事物的基本原理模式),当您只有一个类型来提供与已建立但已损坏的习惯用法的向后兼容性时,它们允许调用静态成员函数。


就像这样,因为标准规定它就是这样工作的。N3290第9.4条规定:

A static member s of class X may be referred to using the qualified-id
expression X::s; it is not necessary to use the class member access
syntax (5.2.5) to refer to a static member. A static member may be
referred to using the class member access syntax, in which case the
object expression is evaluated. [ Example:

1
2
3
4
5
6
7
8
9
10
struct process {
  static void reschedule();
};

process&amp; g();

void f() {
  process::reschedule(); // OK: no object necessary
  g().reschedule(); // g() is called
}

end example ]


如果你不赞同"因为标准是这样说的"因果关系学派,我也建议静态方法已经足够成熟,可以追溯到人们真正担心将this参数传递给函数调用所带来的额外开销的时候,因此将纯函数"静态"作为优化可能是1中最流行的方法。985。