Как глубоко скопировать конструктор с уникальным указателем внутри класса шаблона?

0

Итак, перейдя из Linked List, мне теперь нужно построить Linked Stack, который, я думаю, в значительной степени похож на него. Тем не менее, я получаю ошибку доступа, говоря, что не может получить доступ к частному члену. Я знаю, что это связано с конструктором внутри уникального указателя, где вы не можете скопировать указатель. Один из парней сказал мне сделать глубокую копию конструктора, но я не знаю, как это сделать. Кто-нибудь, пожалуйста, покажет мне, как это сделать? Спасибо.

PS: Я знаю, что этот был опубликован мной ранее сегодня. Но у меня пока нет ответа, и кажется, что никто не отвечает мне ни на что, поэтому я решу его перепроверить. Если вы считаете, что это repost, не стесняйтесь его удалять.

LinkNode.h

#include <iostream>
#include <memory>
using namespace std;

template <class T>
class LinkedNode 
{

    public:
            // This is giving me error and I do not know how to recreate
            // or deep-copy the constructor
        LinkedNode(T newElement, unique_ptr<LinkedNode<T>> newNext)
        {
                element = newElement;
                next = newNext  
        }

        T GetElement() {return element;}

        void SetElement(T x) {element = x;}

        unique_ptr<LinkedNode<T>> newNext() {return next;}

        void SetNext(unique_ptr<LinkedNode<T>> newNext) {next = newNext;}

    private:
        T element;
        unique_ptr<LinkedNode<T>> next;
};

CompactStack.h

#pragma once
#include"LinkedNode.h"

using namespace std;

template <class T>
class CompactStack 
{

    public:

        CompactStack() {}
        bool IsEmpty() const { return head == 0; }

        T Peek() 
        {
            assert(!IsEmpty());
            return head-> GetElement();
        }

        void Push(T x) 
        {
            unique_ptr<LinkedNode<T>> newhead(new LinkedNode<T>(x, head));
            head.swap(newhead);
        }

        void Pop() 
        {
            assert(!IsEmpty());
            unique_ptr<LinkedNode<T>> oldhead = head;
            head = head->next();
        }

        void Clear() 
        {
            while (!IsEmpty())
            Pop();
        }

    private:
        unique_ptr<LinkedNode<T>> head;
};

Это ошибка, которую я получил от компилятора

Error   1   error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' e:\fall 2013\cpsc 131\hw4\hw4\hw4\compactstack.h    23
Теги:
pointers
constructor
unique

2 ответа

2

unique_ptr должен использовать move для перехода от одного unique_ptr к другому. Ниже я добавил все шаги, необходимые для компиляции. Обратите внимание, что после перемещения исходный объект находится в действительном и неизвестном состоянии. Это важно в методе Pop().

Кроме того, неправильная практика заключается в том, чтобы using namespace в заголовке, поэтому они были удалены.

LinkedNode.h

#pragma once
#include <memory>

template <class T>
class LinkedNode
{
public:
    LinkedNode(T newElement, std::unique_ptr<LinkedNode<T>> newNext)
    {
        element = newElement;
        next = move(newNext);
    }
    T GetElement() {return element;}
    void SetElement(T x) {element = x;}
    std::unique_ptr<LinkedNode<T>> newNext() {return move(next);}
    void SetNext(std::unique_ptr<LinkedNode<T>> newNext) {next = move(newNext);}

private:
    T element;
    std::unique_ptr<LinkedNode<T>> next;
};

CompactStack.h

#pragma once
#include <cassert>
#include"LinkedNode.h"

template <class T>
class CompactStack
{
public:
    CompactStack() {}
    bool IsEmpty() const { return head == nullptr; }
    T Peek()
    {
        assert(!IsEmpty());
        return head-> GetElement();
    }
    void Push(T x)
    {
        std::unique_ptr<LinkedNode<T>> newhead(new LinkedNode<T>(x, move(head)));
        head.swap(newhead);
    }
    void Pop()
    {
        assert(!IsEmpty());
        std::unique_ptr<LinkedNode<T>> oldhead = move(head);
        head = oldhead->newNext(); // head no longer valid after move, use oldhead
        // oldhead->next no longer valid, but local variable going out of scope anyway.
    }
    void Clear()
    {
        while(!IsEmpty())
            Pop();
    }
private:
    std::unique_ptr<LinkedNode<T>> head;
};

Вышеуказанное работает с простым тестом:

#include <iostream>
#include "CompactStack.h"
using namespace std;
int main()
{
    CompactStack<int> cs;
    cout << "IsEmpty " << cs.IsEmpty() << endl;
    cs.Push(1);
    cout << "IsEmpty " << cs.IsEmpty() << endl;
    cout << "Peek " << cs.Peek() << endl;
    cs.Push(2);
    cout << "IsEmpty " << cs.IsEmpty() << endl;
    cout << "Peek " << cs.Peek() << endl;
    cs.Push(3);
    cout << "IsEmpty " << cs.IsEmpty() << endl;
    cout << "Peek " << cs.Peek() << endl;
    cs.Pop();
    cout << "IsEmpty " << cs.IsEmpty() << endl;
    cout << "Peek " << cs.Peek() << endl;
    cs.Clear();
    cout << "IsEmpty " << cs.IsEmpty() << endl;
}

Вывод

IsEmpty 1
IsEmpty 0
Peek 1
IsEmpty 0
Peek 2
IsEmpty 0
Peek 3
IsEmpty 0
Peek 2
IsEmpty 1
  • 0
    потрясающая работа! Большое спасибо Марк Толонен
  • 0
    просто быстрый вопрос. Поскольку у нас нет никакой переменной для отслеживания количества элементов, которые мы помещаем в стек, (очевидно, стек никогда не будет переполнен в любом случае), есть ли в любом случае, что мы можем сказать, сколько элементов у нас в определенное время?
Показать ещё 1 комментарий
0

У вас есть еще одна ошибка рядом с той, которую вы указали.

LinkNode::next является приватным. Вы не можете получить доступ к частному члену непосредственно вне класса (или функции друга). Используйте setNext.

  • 0
    Это неверно Частный доступ происходит из-за того, что экземпляр копирования std::unique_ptr unique_ptr является частным в реализации MSVC. std::unique_ptr только для перемещения и не может быть скопирован.
  • 0
    @JesseGood: есть идеи, как сделать семантическое движение?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню