我是C ++的新手,我正在尝试使用LinkedListIterator实用程序类编写LinkedList类,如下所示。 (我只列出了与问题相关的代码部分)。我已将LinkedListIterator构造函数创建为私有。
现在,当我在main()中有这两行时,
LinkedListIterator iter = list->begin(); <<== No compilation error
LinkedListIterator iter2; <<==== compilation error.
我得到第二行的编译错误,这是默认构造函数是私有的。但是,我不明白为什么第一行没有编译错误?为什么?什么叫代码的第一行?私有构造函数或复制构造函数或赋值运算符?
class LinkedListIterator {
public:
bool operator== (LinkedListIterator i) const;
bool operator!= (LinkedListIterator i) const;
void operator++ (); // Go to the next element
int& operator* (); // Access the current element
inline Node* hasnext();
inline Node* next();
private:
LinkedListIterator(Node* p); <<==== Private constructor
LinkedListIterator(); <<==== Private constructor
Node* p_;
friend class LinkedList;//LinkedList can construct a LinkedListIterator
};
....
inline LinkedListIterator::LinkedListIterator(Node* p)
: p_(p)
{ }
inline LinkedListIterator::LinkedListIterator()
{ }
inline LinkedListIterator LinkedList::begin()
{
return first_;
}
inline LinkedListIterator LinkedList::end()
{
return NULL;
}
.......
class LinkedList {
public:
void append(int elem); // Adds elem after the end
void printList();
LinkedList() {
first_ = NULL;
}
LinkedListIterator begin();
LinkedListIterator end();
LinkedListIterator erase(int elem);
private:
Node* first_;
};
main()
{
LinkedList *list = new LinkedList();
list->append(1);
list->append(2);
list->append(3);
LinkedListIterator iter = list->begin(); <<== No compilation error
LinkedListIterator iter2; <<==== compilation error.
}
答案 0 :(得分:8)
LinkedListIterator iter = <some other LinkedListIterator>
被称为复制初始化并调用&#34;隐藏&#34;构造函数:复制构造函数(C ++ 03)。移动构造函数(如果存在,如果初始化程序是临时的,则在C ++ 11中)。这两个构造函数未在您的代码中提供,但它们存在:它们由编译器生成,并且它们是作为公共生成的。因此,可以从类外部访问它们,并且不会出现编译器错误。
Bartek在他的回答中提到了复制省略,所以为了清楚起见,我将添加我的评论:复制/移动ctor必须是可访问的(在这种情况下:公共)进行复制初始化,无论是否进行复制省略或不,即使它没有被召唤。
答案 1 :(得分:3)
没有编译错误,因为构造函数是从LinkedList
类(特别是来自其begin()
成员函数)调用的(即“对象是在...中创建的)”,这是一个{{1 }}。没有其他人可以实例化该类,因此第二行失败。
具体来说,看friend
:
begin()
它(关于访问权限)相当于:
inline LinkedListIterator LinkedList::begin()
{
return first_;
}
调用 return LinkedListIterator(first_);
private
。
然后,可以执行复制椭圆 ,或者可以调用默认公开的默认复制(或移动)构造函数。