【问题标题】:Nested class "does not name a type"嵌套类“没有命名类型”
【发布时间】:2020-05-26 21:23:53
【问题描述】:

我收到以下错误:

main.cpp:18:5: error: 'Iterator' does not name a type
   18 |     Iterator begin() {
      |     ^~~~~~~~

使用此代码:

#include <iostream>
#include <iostream>
#include <memory>
#include <fstream>
#include <filesystem>

using namespace std;

class Numbers {
    private:
    int current;
    int end;

    public:

    Numbers(int end) : current(0), end(end) {}

    Iterator begin() {
        return Iterator(this);
    }

    bool operator==(const Numbers& other) const {
        return current == other.current && end == other.end;
    }

    bool operator!=(const Numbers& other) const {
        return !(other == *this);
    }

    class Iterator {
        private:
        Numbers* range;

        public:
        using value_type = int;
        using difference_type = ptrdiff_t;
        using pointer = int*;
        using reference = int&;
        using iterator_category = input_iterator_tag;

        Iterator(Numbers* range) : range(range) {}

        int operator*() const {
            return range->current;
        }

        int* operator->() const {
            return &range->current;
        }

        bool operator==(const Iterator& other) const {
            return other.range == range;
        }

        bool operator!=(const Iterator& other) const {
            return !(*this == other);
        }

        Iterator& operator++() {
            range->current++;
            return *this;
        }


    };
};

事实证明,将begin 函数移到嵌套的Iterator 类可以编译。

但这很奇怪 - 嵌套类不遵循与任何其他成员相同的访问规则,这意味着不需要前向引用?

我搜索了网站上关于这个确切问题的其他问题,似乎没有找到答案。

【问题讨论】:

  • Iterator 是什么意思?!内部类应该在使用它的名字之前声明。
  • @VladfromMoscow 我明白了。我当然认为是这样,但是,正如我在此处指出的那样,我在 SO 上读到可能并非如此。另外 - 我在成员函数q 中调用成员函数f 没有问题,其中fq 之后定义。你能解释一下为什么后一个例子与这个问题中描述的情况不同吗?谢谢

标签: c++ class scope nested declaration


【解决方案1】:

从评论到问题

另外 - 我在成员函数中调用成员函数 f 没有问题 q 其中 f 在 q 之后定义。你能解释一下为什么后一个例子 与本问题中描述的情况不同?

根据 C++ 20 标准(11.4 类成员)

6 一个类的完整类上下文是一个

> (6.1) — 函数体 (9.5.1),

(6.2) — 默认参数 (9.3.3.6),

(6.3) — 无异常说明符 (14.5),或

(6.4) — 默认成员初始化器

在类的成员规范内

因此,在完整的类上下文中,函数 f 的名称在函数 q 的主体中可见。

但是,内部类是在完整的类上下文之外声明的。所以根据C++ 20 Standard(6.5.1 Unqualified name lookup)

7 用于定义类 X23 之外的名称 X 的完整类上下文 (11.4) 应在以下之一中声明 以下方式:

> (7.1) — 在 X 类中使用或成为 X 基类的成员之前 (11.8),或 ...

因此,内部类的名称Iterator必须在用作成员函数的返回类型之前声明。

您可以使用例如占位符auto 作为返回类型来代替名称迭代器。

auto begin() {
    return Iterator(this);
}

【讨论】:

  • TL;DR:成员函数的定义隐式地“放置在”类之后,因此即使某些内容是在您编写函数体的位置之后声明的,它们也可以看到类中的所有内容。语言中没有“类成员不需要前向声明”规则。成员的声明按照你写的顺序保留在类中,所以begin的签名看不到Iterator
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 2022-01-21
  • 2023-04-07
相关资源
最近更新 更多