C++ 什么时候公共/私人订单不是一种风格选择?

C++ 什么时候公共/私人订单不是一种风格选择?,c++,visual-studio,visibility,declaration,inner-classes,C++,Visual Studio,Visibility,Declaration,Inner Classes,所以通常我遵循的惯例是将我的公共成员函数放在我的私有属性之前,比如 class SomeClass { public: void amazingMethod(); private: int fantasticAttribute; }; 因为包括我在内的用户希望在类中首先看到的是我可以使用的东西。然而,我最近的一个项目引入了一些真正的怪异 template<typename T> class LinkedList { public: class LinkedL

所以通常我遵循的惯例是将我的公共成员函数放在我的私有属性之前,比如

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;
};
一切都编译正确!这只是VisualStudio的一个怪癖吗?我猜这与它是一个模板类这一事实有关,但我不知道


我怎么知道我什么时候必须像大多数惯例所建议的那样,含泪离开首先宣布公众成员的位置?什么时候它不仅仅成为一种风格选择?

它与公共和私人本身无关。它与在使用点是否定义了节点有关。

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

但是,由于迭代器类仅使用指向节点类型的指针,因此前向声明就足够了。以下代码添加了转发声明并进行了编译:

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;
}

如果要首先声明公共成员,请重新定义:

template<typename T>
class LinkedList {
public:
    class LinkedListIterator;
    LinkedListIterator begin();
private:
    struct Node;
    Node* head;
};

template<typename T>
struct LinkedList<T>::Node {
    Node* next;
};

template<typename T>
class LinkedList<T>::LinkedListIterator {
public:
    LinkedListIterator(Node* node);
    LinkedListIterator& operator++();
private:
    Node* node;
};

template<typename T>
LinkedList<T>::LinkedListIterator::LinkedListIterator(Node* node) : node(node) {}

template<typename T>
typename LinkedList<T>::LinkedListIterator& LinkedList<T>::LinkedListIterator::operator++() {
    if (node != nullptr) {
        node = node->next;
    }
    return *this;
}

template<typename T>
typename LinkedList<T>::LinkedListIterator LinkedList<T>::begin() {
    return LinkedListIterator(head);
}

对我来说很有意义-尚未看到类型节点。我相信一位语言律师会为你们提供描述语言的标准的章节-我不知道,但我想你可以一直使用结构节点;在迭代器声明之上。由于指向此结构的指针被用作公共类中公共函数的参数,所以没有理由认为该行不能是公共的?作为解决问题的一部分,通常最好先尝试反驳您的假设。你的假设是它与私人/公共。。。所以,让所有的事情公开——你会看到一个命令编译,但另一个不这样做。事实上,没有什么能阻止我们拥有多个私有块和公共块,你可以考虑基于这个问题放松/概括样式指南。
template<typename T>
class LinkedList {
public:
    class LinkedListIterator;
    LinkedListIterator begin();
private:
    struct Node;
    Node* head;
};

template<typename T>
struct LinkedList<T>::Node {
    Node* next;
};

template<typename T>
class LinkedList<T>::LinkedListIterator {
public:
    LinkedListIterator(Node* node);
    LinkedListIterator& operator++();
private:
    Node* node;
};

template<typename T>
LinkedList<T>::LinkedListIterator::LinkedListIterator(Node* node) : node(node) {}

template<typename T>
typename LinkedList<T>::LinkedListIterator& LinkedList<T>::LinkedListIterator::operator++() {
    if (node != nullptr) {
        node = node->next;
    }
    return *this;
}

template<typename T>
typename LinkedList<T>::LinkedListIterator LinkedList<T>::begin() {
    return LinkedListIterator(head);
}