【问题标题】:Pure virtual functions in C++11C++11 中的纯虚函数
【发布时间】:2014-01-18 15:01:12
【问题描述】:

在 C++98 中,空指针由文字 0 表示(或者实际上是任何值为 0 的常量表达式)。在 C++11 中,我们更喜欢 nullptr。但这不适用于纯虚函数:

struct X
{
    virtual void foo() = nullptr;
};

为什么这不起作用?这不是完全有道理吗?这仅仅是一个疏忽吗?会修复吗?

【问题讨论】:

标签: c++ c++11 virtual pure-virtual nullptr


【解决方案1】:

因为语法是 0,而不是 表达式 或其他一些非终结符匹配 nullptr

一直以来,只有0 有效。甚至0L 也会是格式错误的,因为它与语法不匹配。

编辑

Clang 允许 = 0x0= 0b0= 00 (31.12.2013)。这是不正确的,当然应该在编译器中修复。

【讨论】:

  • @TemplateRex:仅当 NULL 被定义为单字符文字 0 时。
  • @stefan:很少有,一个常见的定义例如是 C 中的(void*)0
  • @MatthieuM.: 在 C++ 中 NULL 必须是整数零,不允许使用 (void*)0(如在 C 中)。
  • @Zac 对,因为宏被它到达编译器的时间所取代。这里的用词不当(尽管已经解释过语法必须是= 0)是人们将NULL0 关联起来。有人应该复制David Rodríguez - dribeas 的引用:“.. vtable 不是语言要求,而只是虚拟方法的一个实现选项。...不同的实现(即,没有 vtable,并且没有任何元素存在 0)”
  • @Nye 感谢您的评论,以便我可以消除误解。我告诉他语法说“= 0”是预期的。我特别没有说“因为就是这样”,因为我自己会否决这样的答案。
【解决方案2】:

virtual 函数的 = 0 符号并不是字面上的“赋值 null”,而是一种实际上具有欺骗性的特殊符号:也可以实现纯虚函数。

对于各种上下文关键字,允许abstract 而不是= nullptr 并让abstract 成为上下文关键字会更有意义。

【讨论】:

  • FWIW,我们得到= 0 而不是abstract 的原因是(简而言之)Bjarne 认为他无法在历史的曙光中将另一个关键字推回 C++ 委员会。我认为这是他的个人遗憾清单,尽管是轻微的。
【解决方案3】:

语法就是这样定义的,如果我们查看draft C++ standard部分9.2类成员相关语法如下:

[...]
member-declarator:
 declarator virt-specifier-seqopt pure-specifieropt
[...]
pure-specifier:
  = 0
  ^^^

语法明确指出 pure-specifier= 0 而不是 整数文字表达式,这似乎并不留下任何回旋的余地。如果我尝试这样的事情:

virtual void foo() = 0L;

或:

virtual void foo() = NULL ;

gcc 告诉我:

错误:';' 之前的纯说明符无效(只允许使用 '= 0')令牌

clang 说:

错误:函数的初始化器看起来不像纯说明符

虽然以下方法在这两种情况下都有效:

#define bar 0
//...
virtual void foo() = bar;

似乎clang 允许八进制文字十六进制文字二进制文字为零,这是不正确的行为。

更新

显然Visual Studio 接受NULL 和任何零整数文字,包括0L0x000 等...虽然它不接受nullptr。 p>

【讨论】:

  • @ECrownofFire:我认为 GCC 4.8 在诊断消息方面有很大改进。
【解决方案4】:

= 0 在那里有固定的含义。它不是真正的整数零。因此,您不能简单地那样替换它。

【讨论】:

    【解决方案5】:

    = 0 语法不用于初始化指针,它只是在语法上表明提供的 virtual 是纯的。

    因此用于声明纯virtuals 的= 0 语法没有改变。

    【讨论】:

      【解决方案6】:

      nullptr 的全部要点(或大部分要点)只能分配给(或用于初始化)指针。

      在这种情况下,您没有初始化或分配给指针,因此在这种情况下您能够使用它甚至没有意义。

      【讨论】:

      • 为什么不呢?函数通常退化为函数指针,所以我不明白为什么这种语法没有意义。当时他们只是没有nullptr 关键字可用。
      • @user2345215:因为 =0 在这种情况下并不意味着“将 null 分配给这个指针”,它意味着完全不同的东西。
      • 这并不是字面意思。但我认为这仍然是有道理的。它会将函数的地址设置为零指针(如果您可以实际修改它),就好像该函数无处可去。但这就是纯虚函数的意义所在。
      • @user2345215:除了那不一定是真的。正如 Dietmar 已经指出的那样,您可以创建一个纯虚拟函数实现该函数,在这种情况下,vtable 中的该槽将包含实际函数的地址。
      • @user2345215:您只知道空指针将被分配到某个地方(Jerry 指出的情况除外),因为您熟悉平台的虚拟实现。 C++ 标准没有规定必须使用 vtbl,或者任何关于 如何 virtual 的实现——只有效果应该是什么。通过将nullptr 合并为pure,标准将隐含承认平台细节。
      【解决方案7】:

      这并不意味着它是一个指针,或者它必须等于nullptr

      = 0 就足够了,意味着虚函数是纯的。

      【讨论】:

        【解决方案8】:

        C++11 语法在这里只允许0 (并不意味着指针)。因为nullptr 不是0,所以它失败了。 NULL 仅在 NULL 定义为 0 时有效(有时是这种情况,但并非总是如此)。只需在这里使用0,或者使用下面的define(如果你真的想使用null,当它不是指针时)。

        #define VIRTUAL_NULL 0
        struct X
        {
            virtual void foo() = VIRTUAL_NULL;
        };
        

        【讨论】:

          猜你喜欢
          • 2016-10-13
          • 2012-12-02
          • 2012-11-20
          • 1970-01-01
          • 1970-01-01
          • 2023-03-27
          • 2017-09-09
          • 2016-07-22
          • 1970-01-01
          相关资源
          最近更新 更多