我们能否拥有静态虚函数?如果不能,那么为什么?

69

可能是重复问题:
C++中的静态虚函数?

我们能否拥有静态虚函数?如果不能,那么为什么?

class X
{
public:
       virtual static void fun(){} // Why we cant have static virtual function in C++?
};

一个可能的解决方案是在基类中创建一个静态方法(但不是虚拟的),并使其调用派生类中等效的静态方法。这样,您仍然保持封装和多态性。 - anni
2个回答

72

不可以,在C ++中没有意义。

当您拥有一个指向类的实例的指针/引用时,才会调用虚函数。静态函数不与特定实例绑定,而是与类绑定。 C++没有指向类的指针,因此不存在可以虚拟调用静态函数的情况。


8
“Doesn't make any sense”? 那 Python 中的类方法呢? - user541686
53
语言可以很容易地决定为每个类添加一个静态虚函数表。 - Inverse
9
@OliCharlesworth:没错。这是完全有可能存在的,只是目前还没有出现而已。但这肯定是有道理的(并且会很有用)。 - user541686
13
敬启者,对于某些用途和某些人来说,虚拟静态成员确实是有意义的。@OliverCharlesworth,请考虑重新表述您的回答或更详细地说明。是的,我知道它已经被接受了,但是——就其现状而言,这并不正确。 - einpoklum
3
如果需要,你可以在对象上调用静态函数,对吗?这种情况下,你可以使用虚函数表来确定要调用哪个版本的函数。当从类的非静态成员函数内部调用时,这尤其有意义。 - PieterNuyts
显示剩余18条评论

9

这样做没有意义。 虚拟成员函数的重点在于它们根据调用它们的对象实例的动态类型进行分派。另一方面,静态函数与任何实例无关,而是类的属性。因此,让静态函数成为虚函数是没有意义的。如果必须这样做,可以使用非静态分发器:

struct Base
{
    static void foo(Base & b) { /*...*/ }

    virtual ~Base() { }
    virtual void call_static() { foo(*this); /* or whatever */ }
};

struct Derived : Base
{
     static void bar(int a, bool b) { /* ... */ }

     virtual void call_static() { bar(12, false); }
};

使用方法:

Base & b = get_instance();
b.call_static();   // dispatched dynamically

// Normal use of statics:
Base::foo(b);
Derived::bar(-8, true);

33
你一直说这个“没有意义”,但是你提供的例子表明,语言支持调用派生类中的静态函数可能是合理的。 - Inverse
3
如果函数是纯虚函数并且带有函数体,那么它就有意义了。然后,如果您在派生类中不重载它,编译器将会报错。例如,考虑一个用于创建单例的getInstance()函数。您可能希望有一个契约,即每个从此基类派生的类都必须具有getInstance()函数。您希望编译器为您检查这一点。 - xryl669
68
在SO上,每个C++问题都被回答为“因为它没有意义”吗?我刚刚创建了一个虚拟方法,因为它必须被重写,然后我意识到它不应该(而且真的不能)触及任何实例数据,所以我给它添加了static修饰符,这就是我来到这个页面的原因。这个回答提供了一种解决方法(+1),但是它未能回答问题,因为“它没有意义”显然是错误的。 - sh1
9
static 不仅意味着可以在没有类实例的情况下调用,它还承诺不会访问 this。这有点类似于一个纯函数(例如 constexpr,它显然也禁止使用 virtual)。一个函数既可以是纯函数(在数学意义上),同时也可以是虚函数。C++ 只是规定这样的函数接收一个虚假的 this 指针,这就取走了在派生类上强制执行 static 契约的可能性。 - sh1
2
只是想为sh1表达一些支持。如果c++是许多开发人员暗示的超级严格的每个关键字都有一个意思的语言,那么这“没有意义”,但实际上并非如此。虽然static virtual的实现显然不会像普通的静态方式那样工作,但“virtual”所做的事情不止一个部分。在这种情况下,他正在寻找编译器错误,如果未定义静态函数,则会出现编译器错误。编译器可以轻松地忽略vtable而执行此操作。多功能动词是真实存在的。 - Seph Reed
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接