【问题标题】:The role of access specifiers on typedefs and forward declaration访问说明符在 typedef 和前向声明中的作用
【发布时间】:2014-02-27 14:29:35
【问题描述】:

考虑以下链表类型类的示例代码。我希望声明一个返回迭代器的方法,它是 typedefNode*。但是,Node 是一个私有嵌套类,所以为了生成 typdef,我需要通过前向声明让编译器知道 Node

天真地,我认为将两者都默认为私有会起作用;像这样:

class List
{
    class Node;
    typedef Node* Iterator;
public:
   List() : head_(NULL), tail_(NULL) {} 
   Iterator begin() {return head_;}

private:
    class Node
    {
        private:
        int data_;
    };

    Node* head_;
    Node* tail_;
};

int main()
{
    List list;
    List::Iterator = list.begin();
    return 0;
}

导致第 4 行出现编译时错误:

'typedef class List::Node* List::Iterator' 是私有的
编译因 -Wfatal-errors 而终止。

不难看出为什么前向声明class Node; 属于私有部分,但是typedef Iterator Node*; 呢?这可能是由于我对 typedef 关键字缺乏了解,但为什么应用哪个访问说明符很重要?我认为 private 更有意义,因为 Node 类的可见性。

这是否与typedefs 成为公共接口的一部分有关?是否必须使用 public 可见性声明所有类型定义?


编辑: 请允许我澄清一下,我知道我可以通过将 typedef 移至 public 来阻止我的编译器抱怨。我不明白为什么这是必要的。

【问题讨论】:

  • 如果我在类定义的末尾添加一个分号,我不会收到任何错误。这是你的真实代码吗?
  • 啊,原来如此.. 这只是一个简化版本。我会看看我是否可以重新创建错误
  • @StickyCube - 也许你试图使用非朋友类/函数中的Iterator 类型?
  • 好的,我添加了一个小实现。我现在再次收到错误

标签: c++ typedef nested-class forward-declaration access-specifier


【解决方案1】:

您可以简单地将 typedef name 设为公共名称。试试下面的

class List
{
public:
    typedef class Node* Iterator;

还要考虑到对于这两个类,您忘记在右大括号后放置分号。:)

【讨论】:

    【解决方案2】:

    List::Iterator是私有的,所以不能用名字,但是可以推导出类型

    List l;
    List::Iterator it = l.begin(); // Illegal
    auto it = l.begin(); // legal
    

    template <typename IT>
    void foo(IT it);
    
    foo(l.begin()); // legal
    

    顺便说一句,您可能拥有List::Iterator 公开,并保持List::Node 私有。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-19
      • 2010-10-22
      • 2011-01-28
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      • 2018-11-02
      • 1970-01-01
      相关资源
      最近更新 更多