【问题标题】:Can static functions be virtual in C++?静态函数可以在 C++ 中是虚拟的吗?
【发布时间】:2020-12-26 18:32:45
【问题描述】:

我发现了一些关于我上述问题的陈述,但有不同的说法:

  1. 静态成员函数不能访问类的非静态数据成员/函数。 vPTR 是非静态数据成员,因此静态成员函数无法访问 vPTR。

  2. 不,因为它在 C++ 中没有任何意义。

    当你有一个类实例的指针/引用时,就会调用虚拟函数。静态函数不绑定到特定实例,它们绑定到类。 C++ 没有指向类的指针,因此没有可以虚拟调用静态函数的场景。

哪一个是正确的,出于什么原因?

【问题讨论】:

  • 虚拟静态函数没有意义。虚函数用于为特定对象选择正确的实现。而且静态函数不是基于对象,而是基于类。
  • 还有为什么静态成员函数不能声明为 const, volatile, 或 const volatile.??
  • @user253751 虽然好看也挺好看的。
  • 静态函数不能是const,原因与virtual 相同——它只对在对象上调用的函数有意义。 const应用于成员函数使得this指针const,而静态成员函数没有任何this指针。
  • 实际上,我过去已经在 OOP 中看到过类函数(可以与 static virtual 函数相媲美)。这是一个用 C 编写的 OOP API。但是,语言不支持这样的功能,但它可能通过函数指针和/或编译时多态(又名模板)以某种方式实现。

标签: c++ static


【解决方案1】:

不,静态函数在 C++ 中不能是虚函数。

如果函数不依赖于类的任何成员,但在某种意义上依赖于类型,它有时会很有用:

struct Animal
{
    static virtual std::string whatNoiseDoIMake() = 0;
};

struct Dog : Animal
{
    static std::string whatNoiseDoIMake()
    {
        return "woof"s;
    }
};

它不属于该语言的原因是它没有被 C++ 标准委员会提议和接受。我的示例可以使用类型特征来解决,这削弱了允许此类构造的情况。

至于const,这确实是关于修改非mutable 类成员的可能性。编造一个有意义的 const static 成员函数示例更难。也许它可以适用于static 成员,但是这样的成员无论如何都可以通过:: 访问,但(有趣的是)访问说明符被丢弃了。

【讨论】:

    【解决方案2】:

    哪个是正确的,确切的原因是什么?

    1. 静态成员函数不能访问类的非静态数据成员/函数。 vPTR 是非静态数据成员,因此静态成员函数无法访问 vPTR。

    2. 不,因为它在 C++ 中没有任何意义。

      当你有一个类实例的指针/引用时,就会调用虚拟函数。静态函数不绑定到特定实例,它们绑定到类。 C++ 没有指向类的指针,因此没有可以虚拟调用静态函数的场景。

    第一个说法是正确的,静态成员函数无法访问*this 指针,它们具有类作用域。静态成员由类的所有实例共享

    在第二个陈述中,第一部分是基于意见的,可以说它可能有用,as @Bathsheba points out。第二部分是正确的。

    无论使用这种结构的意义或优点如何,标准都清楚地说明了为什么不允许使用虚拟静态成员函数:

    11.7.2 虚函数 [class.virtual#11]

    [ 注意:virtual 说明符暗示成员资格,因此虚函数不能是非成员 ([dcl.fct.spec]) 函数。 虚函数也不能是静态成员,因为虚函数调用依赖于特定对象来确定调用哪个函数。 在一个类中声明的虚函数可以在另一个类中声明为朋友 ([class.friend])。 ——尾注 ]

    【讨论】:

      【解决方案3】:

      不,他们不能。

      虚拟成员旨在处理类的实例

      静态成员不处理实例,它们只与有关。

      由于没有与任何实例的连接,您将如何根据实例(如在动态多态中)选择调用哪个“虚拟静态”函数?

      这只是两种具有相互排斥依赖关系的不同机制。

      【讨论】:

        【解决方案4】:

        静态函数在 C++ 中可以是虚函数吗?

        没有。

        静态成员函数不能访问类的非静态数据成员/函数。

        这不太对:静态方法绝对可以访问非静态(实例)成员...... 如果你给他们一个实例。他们有访问权限,只是没有可操作的默认this 对象。

        vPTR 是非静态数据成员,因此静态成员函数无法访问 vPTR

        我们不需要详述 vtable 等实现细节。说虚拟分派依赖于对象的动态类型就足够了,如果你没有一个对象,那么虚拟分派就不会产生类型歧义。

        C++ 没有指向类的指针,因此没有可以虚拟调用静态函数的场景

        请注意,在具有此功能的语言中,您仍然不需要用于静态虚拟的特殊系统 - 通常只是类 对象。所以在这种情况下,普通类的静态方法仍然是类object的实例方法。

        【讨论】:

          【解决方案5】:

          第一个语句假定一个“vptr”。这指的是 C++ 编译器中的一种常见实现技术,其中每个具有虚函数的对象都包含一个指向某个“vtable”的隐藏指针,而该指针又包含指向虚函数的指针。

          然而,这是那些编译器的实现细节。他们选择了该实现因为它是 C++ 标准允许的可能实现。

          它被允许的原因之一是因为 C++ 标准说你总是需要一个对象来调用一个虚函数,所以总是有一个对象来存储这个“vptr”。

          因此,第一个答案混淆了因果关系。实现可以使用“vptr”因为虚函数需要一个对象,因此不能是static,反之亦然。

          【讨论】:

            【解决方案6】:

            静态函数在 c++ 中不能是虚拟的,因为这个概念会导致编译错误并且基本上在运行时解决

            【讨论】:

            • 欢迎来到 StackOverflow!您能否举个例子让您的回答更有影响力?
            猜你喜欢
            • 2015-12-06
            • 1970-01-01
            • 1970-01-01
            • 2013-03-26
            • 2016-02-05
            • 2010-09-20
            • 2011-11-05
            • 2012-06-10
            • 2016-01-16
            相关资源
            最近更新 更多