为什么要调用静态成员函数。或 - >语法合法吗?

时间:2012-08-15 20:55:19

标签: c++ static member-functions

  

可能重复:
  C++ Static member method call on class instance

今天我发现我曾经长期存在的东西(我的意思是 - 像二十年一样),在C ++中被认为是非法的,实际上是合法的。即,调用静态成员函数,就好像它属于单个对象一样。例如:

struct Foo
{
    static void bar() { cout << "Whatever."; }
};

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

我通常会看到使用“范围分辨率语法”严格调用静态成员函数,因此:

Foo::bar();

这是有道理的,因为静态成员函数不与类的任何特定实例相关联,因此我们不希望特定实例在语法上“附加”到函数调用。

然而我今天发现GCC 4.2,GCC 4.7.1和Clang 3.1(作为编译器的随机抽样)接受前一种语法,以及:

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

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

为什么C ++允许调用静态成员函数,就好像它们是单个对象的直接成员一样 - 即使用。或 - &gt;附加到对象实例的语法?

5 个答案:

答案 0 :(得分:14)

C ++的设计和演变(第288页)中,Bjarne Stroustrup提到在静态成员函数之前的几天,程序员使用像((X*)0)->f()这样的黑客来调用没有成员函数的成员函数需要一个对象。我的猜测是,当静态成员函数添加到该语言时,允许通过->进行访问,以便具有此类代码的程序员可以将f更改为static,而无需进行搜索和更改每次使用它。

答案 1 :(得分:9)

据推测,你可以在你可能不知道类的东西的地方调用它,但编译器会这样做。

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

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

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

然后在我的代码中我可以执行以下操作:

Foo foo;

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

无需担心一直知道我的对象类。例如,在编写模板时,这将非常方便。

答案 2 :(得分:6)

就像这样,因为标准说它是如何运作的。 n3290§9.4声明:

  

可以使用qualified-id引用类X的静态成员   表达式X::s;没有必要使用类成员访问   语法(5.2.5)引用静态成员。静态成员可以是   引用使用类成员访问语法,在这种情况下   对象表达式进行评估。 [例如:

struct process { 
  static void reschedule(); 
}; 

process& g();

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

结束例子]

答案 3 :(得分:6)

来自The Evolution of C++ (pdf), section 8. Static Member Functions

  

......还观察到了不可移植的代码,例如

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

用于模拟静态成员函数。

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

答案 4 :(得分:1)

如果你没有订阅“因为标准这么说”的因果关系学派,我还建议静态方法已经足够老了,以至于人们实际上担心通过{{1函数调用的参数,因此将纯函数“静态”作为优化可能在1985年风靡一时。