【问题标题】:private constructor in C++C++中的私有构造函数
【发布时间】:2014-05-27 13:58:09
【问题描述】:

我是 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.         

}

【问题讨论】:

    标签: c++ constructor private-constructor


    【解决方案1】:

    LinkedListIterator iter = &lt;some other LinkedListIterator&gt; 被称为 复制初始化 并调用“隐藏”构造函数:复制构造函数 (C++03) 和。移动构造函数(如果存在,并且如果初始值设定项是临时的,在 C++11 中)。您的代码中没有提供这两个构造函数,但它们存在:它们由编译器生成,并且它们是作为公共生成的。因此,它们可以从类外部访问,并且不会出现编译器错误。

    Bartek 在他的回答中提到了复制省略,所以为了清楚起见,我将添加我的评论:复制/移动 ctor 必须可访问(在本例中:公共)以进行复制初始化,无论是否发生复制省略,即即使它没有被调用。

    【讨论】:

    • 感谢 Arne Mertz 的快速响应和详细解释。让我读一下你介绍的新术语:)
    • @user2896235 请注意,“隐藏”不是官方术语,而“复制初始化”是。
    【解决方案2】:

    没有编译错误,因为构造函数是从LinkedList 类(特别是从它的begin() 成员函数)调用的(即“对象是在其中创建的”),这是一个friend。没有其他人可以实例化该类,因此第二行失败。


    具体看begin()

    inline LinkedListIterator LinkedList::begin()
    {
        return first_;
    }
    

    它(关于访问)相当于:

        return LinkedListIterator(first_);
    

    调用privateLinkedListIterator::LinkedListIterator(Node* p)

    然后,可以执行复制省略,或者可以调用默认公共的默认复制(或移动)构造函数。

    【讨论】:

    • 请注意,即使发生复制省略,复制/移动构造函数也必须是公开的才能工作。
    • @ArneMertz 好点。无论如何,您的回答总体上“更正确”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-16
    相关资源
    最近更新 更多