所以通常我会遵循以下惯例:将我的public成员函数放在我的私有(private)属性之前

class SomeClass {
public:
    void amazingMethod();
private:
    int fantasticAttribute;
};

因为用户(包括我)想要在类里面首先看到的是我可以使用的东西。但是,我最近的一个项目引入了一些真正的怪异。
template<typename T>
class LinkedList {
public:
    class LinkedListIterator {
    public:
        LinkedListIterator(Node* node) : node(node) {}
        LinkedListIterator& operator++() {
            if (node != nullptr) {
                node = node->next;
            }
        }
    private:
        Node* node;
    };
    LinkedListIterator begin() {
        return LinkedListIterator(head);
    }
private:
    struct Node {
        Node* next;
    };
    Node* head;
};

此代码在Visual Studio 2015中无法编译,报告Node尝试使用LinkedListIterator时未定义。但是奇怪的是,如果我翻转LinkedList,它被声明为
template <typename T>
class LinkedList {
private:
    //everything that was in private before
public:
    //everything that was in public before
};

一切都能正确编译!这只是Visual Studio的怪癖吗?我猜想这与它是模板类有关,但我不知道。

我怎么知道什么时候我不得不放弃声明公众成员的资格(正如大多数公约所建议的那样)?什么时候不仅仅成为一种风格选择?

最佳答案

它与访问类型无关。它与LinkListIterator有关,试图使用编译器尚未看到的类型。

但是,由于迭代器类仅使用指向Node类型的指针,因此前向声明就足够了。以下代码添加了前向声明并可以正常编译:

template<typename T>
class LinkedList {
private:
    struct Node; // Private forward declaration of the private class

public:
    class LinkedListIterator {
    public:
        LinkedListIterator(Node* node) : node(node) {}
        LinkedListIterator& operator++() {
            if (node != nullptr) {
                node = node->next;
            }
        }
    private:
        Node* node;
    };
    LinkedListIterator begin() {
        return LinkedListIterator(head);
    }
private:
    struct Node {
        Node* next;
    };
    Node* head;
};

int main()
{
    return 0;
}

Live Example

09-13 08:10