【问题标题】:When is forward declaration not enough? [duplicate]什么时候前向声明还不够? [复制]
【发布时间】:2019-10-10 01:45:42
【问题描述】:

#include 问题

class widget { };

class fubar : public widget { // 1

    void value_parameter(widget); // 2    
    void ref_parameter(widget &); // 3
    void ptr_parameter(widget *); // 4

    virtual void value_parameter(widget); // 5
    virtual void ref_parameter(widget &); // 6
    virtual void ptr_parameter(widget *); // 7

    widget value_return(); // 8
    widget & ref_return(); // 9
    widget * ptr_return(); // 10

    widget instance_value_member; // 11
    widget & instance_ref_member; // 12
    widget * instance_ptr_member; // 13

    static widget static_value_member; // 14
    static widget & static_ref_member; // 15
    static widget * static_ptr_member; // 16
};

哪些行需要包含? (#include "widget.hpp")

【问题讨论】:

  • 你认为是哪几行,为什么?
  • 代码暗示widget 是在fubar 之前提供的,但问题的其余部分则相反。如果是第一种情况,则任何成员都不需要#include(已经提供了widget)。如果是第二个,那么您从widget 继承这一事实意味着您需要#include 而不管fubar 的其余定义如何。
  • @Sergio Legaz Ruiz 你忘了标记这条线类 fubar : public widget {..:)
  • 欢迎来到 StackOverflow!请选择一个更具描述性的标题;原样的标题不太可能对未来的访问者有所帮助。
  • .... 说得好听

标签: c++ class overloading definition incomplete-type


【解决方案1】:

Widget 的完整定义需要:

  • #1 (class fubar : public widget),我们需要基类定义。
  • #11 (widget instance_value_member;),我们需要成员定义。

对于其他人来说,前向声明就足够了。

【讨论】:

  • #8 怎么样? #14?
  • @LightnessRacesinOrbit 这是一个声明而不是一个定义。:) 它可能有一个不完整的类型。
  • @LightnessRacesinOrbit 是的,这让我最近也感到惊讶。似乎只有在影响类实例的大小时才需要完整的定义。我想其他一切都留给链接器。
【解决方案2】:

无。

class widget { }; 定义了一个完整类型

如果你写了class widget;前向类声明,情况会有所不同。然后考虑到由于继承而需要一个完整类型,这些函数将不再需要#include

【讨论】:

  • 我怀疑这纯粹是为了说明,尽管我承认这个问题没有很好地提出。
  • @LightnessRacesinOrbit:你必须回答所问的问题。我认为“这将是另一回事”表明我有足够的主动性;-)
【解决方案3】:

我认为你的意思是前向声明

class widget;

而不是定义

class widget { };

在这种情况下是类声明的第一个标题行

class fubar : public widget { // 1

需要一个完整的小部件类型定义。否则类 fubar 的大小将是未知的。

除此行外,所有其他声明都不需要小部件的完整类型定义

widget instance_value_member; // 11

考虑到静态数据成员可能具有不完整的类型,因为它们是类定义中的声明(除非使用说明符 constexpr 声明它们)。所以以这一行为例

static widget static_value_member; // 14

不需要widget的完整类型定义。

你也不能通过以下方式重载成员函数

void value_parameter(widget); // 2    
void ref_parameter(widget &); // 3
void ptr_parameter(widget *); // 4

virtual void value_parameter(widget); // 5
virtual void ref_parameter(widget &); // 6
virtual void ptr_parameter(widget *); // 7

即重载具有相同名称和参数列表的虚拟和非虚拟函数。

【讨论】:

  • @Jarod42 通常编译器不能根据参数是否为引用来选择函数。
  • @Jarod42 哦,我没看到。:)
猜你喜欢
  • 2011-09-08
  • 1970-01-01
  • 1970-01-01
  • 2023-01-28
  • 2017-10-05
  • 1970-01-01
  • 2016-10-29
  • 1970-01-01
  • 2012-10-08
相关资源
最近更新 更多