所以通常我会遵循以下惯例:将我的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