Итак, перейдя из 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
unique_ptr
должен использовать move
для перехода от одного unique_ptr к другому. Ниже я добавил все шаги, необходимые для компиляции. Обратите внимание, что после перемещения исходный объект находится в действительном и неизвестном состоянии. Это важно в методе Pop()
.
Кроме того, неправильная практика заключается в том, чтобы using namespace
в заголовке, поэтому они были удалены.
#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;
};
#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
У вас есть еще одна ошибка рядом с той, которую вы указали.
LinkNode::next
является приватным. Вы не можете получить доступ к частному члену непосредственно вне класса (или функции друга). Используйте setNext
.
std::unique_ptr
unique_ptr является частным в реализации MSVC. std::unique_ptr
только для перемещения и не может быть скопирован.