Possible Duplicate:
C++ static virtual members?
我们能有一个静态虚函数吗?如果没有,为什么?
1 2 3 4 5
| class X
{
public:
virtual static void fun(){} // Why we cant have static virtual function in C++?
}; |
- 一种可能的解决方案是在基类中创建一个静态方法(但不是虚方法),并让它在派生类中调用等效的静态方法。这样,您仍然可以维护封装和多态性。
不,因为它在c++中没有任何意义。
当您拥有指向类实例的指针/引用时,将调用虚函数。静态函数不绑定到特定的实例,而是绑定到类。c++没有指向类的指针,因此不存在可以实际调用静态函数的场景。
- "没有任何意义"?那么Python中的类方法呢?
- 我不懂Python。你能详细吗?
- stackoverflow.com/a/38276/541686
- 好的,但是在什么上下文中它们会被虚拟地调用呢?
- stackoverflow.com/a/136138/541686
- @Mehrdad—这个问题被标记为(并且特别提到)c++。在这种背景下,它确实没有意义。
- @Mehrdad:好的,但是如果没有指针到类这样的东西,只有指针到实例这样的东西,那么如何将其转换成c++呢?
- 该语言可以很容易地决定为每个类添加一个静态虚函数表
- @Attila:我以前也说这没有"意义",但我觉得这有点太强烈了。如果语言是这样实现的,这当然是有意义的——只是碰巧不是这样。
- 那是什么意思呢?在什么上下文中,您可以实际调用静态函数?
- @OliCharlesworth:当你拥有某种类型的工厂(例如虚拟构造器)时,我认为这可能是有意义的。
- 是的,会的。但一个基本的先决条件将是"指针到类"的概念。
- @OliCharlesworth:没错。没有任何理由不存在——只是它不会发生。但这肯定是有意义的(而且会很有用)。
- @Mehrdad:完全同意。我的回答是基于不存在类指针的前提下写的;我将更新它使其显式。
- 那就更有道理了。:P
- 那么,我们如何将(因此是虚拟的)派生类强加给实现了的特定于类(因此是静态的)方法呢?
- @wiktus239:考虑到c++的限制,在什么样的上下文中实施这个会有用?
- 由于c++的限制,它是无效的。然而,它可能发现其使用的上下文是派生出一个抽象类来表示具有静态方法,并具有适合该类的实现。
- 恭敬地说,虚拟静态成员对于某些用途和某些人来说是有意义的。@OliverCharlesworth,考虑重新措辞你的答案或者更详细地阐述。是的,我知道它被接受了,但是,嗯——它现在的情况不是这样的。
- @einpoklum——这在评论讨论中已经重新措辞了——在c++中没有意义,因为c++没有指向类的指针/引用(所以没有办法利用静态多态性)。
- 你可以对一个对象调用一个静态函数,对吧?在这种情况下,可以使用vtable来确定要调用的函数版本。当从类本身的非静态成员函数内部调用时,它尤其有意义。
- 设想一个实现,其中vtables是函数指针列表,每个类一个表,一些函数接受"this"指针,而另一些函数不接受。类的对象在实例化时接收类vtable指针。类vtable仍然可以使用语法类::static_method()静态引用。这在实现方面是有意义的。但问题是c++没有元数据"指向类型的指针",它只有"指向对象的指针",所以它的用处可能有限;在调用方法之前,您需要完全解析的类型,从而降低了虚方法的值
这没有任何意义。虚成员函数的要点是,它们是根据调用它们的对象实例的动态类型来分派的。另一方面,静态函数不与任何实例相关,而是类的属性。因此,它们是虚拟的毫无意义。如果你必须,你可以使用非静态调度器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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); }
}; |
用法:
1 2 3 4 5 6
| Base & b = get_instance();
b.call_static(); // dispatched dynamically
// Normal use of statics:
Base::foo(b);
Derived::bar(-8, true); |
- 您一直说它"毫无意义",但是您提供的示例表明,对于一种语言来说,决定支持它可能是合理的——在派生类中调用静态函数。
- @ reverse除了Base,运行时Base还能是什么?
- 如果函数是纯虚的,那么它就有意义。如果在派生类中不重载编译器,编译器就会出错。以getInstance()函数为例,创建单例。您可能想要一个契约,其中规定从这个基类派生的每个类都必须有一个getInstance()。你想让编译器帮你检查。
- 是不是每个c++问题的答案都是"因为毫无意义"?我只是创建了一个虚拟方法,因为它必须被覆盖,然后我意识到它没有(而且确实不应该)接触任何实例数据,所以添加了静态到其中,这就是我在这个页面上的结果。这个答案提供了一个变通方法(+1),但是没有回答这个问题,因为"没有意义"是完全错误的。
- 我恰好不同意。如果您只听到"c++"、"class"和"virtual"这几个词,那么这个问题听起来可能很合理,但是一旦您掌握了该语言的对象模型,很快就会发现它不是。也许对SO的不同理解在于你对一个问题的背景和准备程度。
- static不仅仅意味着它可以在没有类实例的情况下调用;它还承诺不会访问this。它在某种程度上近似于一个纯函数(像constexpr,它显然也禁止virtual)。函数可以是纯函数(在数学意义上),也可以是虚函数。c++只是强制这样一个函数接收一个伪的this指针,从而消除了将static契约强加于派生类的可能性。
- @sb1您可以const限定这种方法,这是一种更传统的暗示纯度的方法
- 只是想表示对sh1的支持。如果c++是一种超级严格的每一个关键字都意味着一件事的语言,那么它"没有意义",但它确实不是。虽然static virtual的实现显然不会像普通静态那样工作,但是"virtual"的作用不止一个部分。在本例中,如果没有定义静态函数,则查找编译器错误。编译器可以很容易地做到这一点,同时忽略vtables。多用途动词是真实存在的。