如何在使用装饰器和迭代器设计模式时声明友类
How to declare friend classes while using decorator and iterator design patterns
我通过装饰ListAsSLL类(单链表)创建了一个ListAsDLL类(双链表)。现在我想合并一个Iterator类来循环ListAsDLL类。我的代码如下:
#include <iostream>
using namespace std;
class ListAsSLL
{
protected:
struct node{
int i;
struct node* next;
};
node* head;
node* tail;
int listSize;
public:
ListAsSLL()
{
head = 0;
tail = 0;
listSize = 0;
}
virtual void addToBeginning(int i)
{
node * temp = new node;
temp->i = i;
if(head==0){
temp->next = 0;
tail = temp;
}else if(head == tail) {
temp->next = tail;
}
else{
temp->next = head;
}
head = temp;
listSize++;
}
virtual void print()
{
node* temp = head;
for (int i = 0; i < listSize; ++i) {
cout<<temp->i<<" "<<endl;
temp = temp->next;
}
}
};
class Decorator : public ListAsSLL
{
private:
ListAsSLL* list;
public:
Decorator(ListAsSLL* l)
{
list = l;
}
virtual void addToBeginning(int i)
{
list->addToBeginning(i);
}
virtual void print()
{
list->print();
}
};
class PreviousDecorator : public Decorator
{
protected:
struct dnode : public node
{
node* prev;
};
dnode* head;
dnode* tail;
int listSize;
public:
PreviousDecorator(ListAsSLL* l) : Decorator(l)
{
listSize = 0;
head = 0;
tail = 0;
}
virtual void addToBeginning(int i)
{
Decorator::addToBeginning(i);
dnode * temp = new dnode;
temp->i = i;
if(head==0){
temp->next = 0;
tail = temp;
}else if(head == tail) {
temp->next = tail;
tail->prev = temp;
}
else{
temp->next = head;
tail->prev = temp;
}
temp->prev = 0;
head = temp;
listSize++;
}
virtual void print()
{
Decorator::print();
node* temp = head;
for (int i = 0; i < listSize; ++i) {
cout<<temp->i<<" "<<endl;
temp = temp->next;
}
}
friend class DLLIterator;
};
class ListAsDLL : public ListAsSLL
{
public:
virtual void addToBeginning(int i){}
virtual void print(){}
};
class DLLIterator
{
private:
ListAsDLL* dll;
public:
DLLIterator(ListAsDLL* dll)
{
this->dll = dll;
}
int getFirst()
{
return dll->head->i;
}
};
int main() {
ListAsSLL* dll = new PreviousDecorator(new ListAsDLL());
dll->addToBeginning(20);
DLLIterator* it = new DLLIterator((ListAsDLL*) dll);
cout<<it->getFirst()<<endl;
delete dll;
delete it;
return 0;
}
唯一的问题是,因为我正在传递ListAsDLL作为参数到Iterator类,我无法访问它正在装饰的类的受保护属性。因此我不能访问dll->head-> I .
首先,我是否正确地使用了decorator设计模式?其次,我如何访问一个被友类装饰过的类的受保护属性呢?
你的类层次结构是:
ListAsSSL (a first head) <- Decorator <- PreviousDecorator (another head)
^
|---- ListAsDLL
不能将PreviousDecorator
强制转换为ListAsDLL
,即使它们有共同的基类。此外,在PreviousDecorator::addToBeginning
方法中,您写入PreviousDecorator::head
而不是ListAsSSL::head
,从而保留nullptr
。
当您想要定制单元格时,一种解决方案可以是使用像createEmptyNode
这样的虚拟方法在类ListAsSLL
的级别上打开节点的类型。ListAsDLL
可以重写此方法以创建双链接节点,如下面的代码所示。
#include <iostream>
using namespace std;
class ListAsSLL
{
protected:
struct node{
int i;
struct node* next;
};
node* head;
node* tail;
int listSize;
public:
ListAsSLL()
{
head = 0;
tail = 0;
listSize = 0;
}
virtual node* createEmptyNode() const { return new node{}; }
virtual node* addToBeginning(int i)
{
node * temp = createEmptyNode();
temp->i = i;
if(head==0){
temp->next = 0;
tail = temp;
}else if(head == tail) {
temp->next = tail;
}
else{
temp->next = head;
}
head = temp;
listSize++;
return temp;
}
virtual void print()
{
node* temp = head;
for (int i = 0; i < listSize; ++i) {
cout<<temp->i<<" "<<endl;
temp = temp->next;
}
}
};
class ListAsDLL : public ListAsSLL
{
protected:
struct dnode : public node
{
dnode* prev;
};
virtual node* createEmptyNode() const { return new dnode{}; }
public:
virtual node* addToBeginning(int i)
{ node* result = ListAsSLL::addToBeginning(i);
static_cast<dnode*>(tail)->next = static_cast<dnode*>(result);
static_cast<dnode*>(result)->prev = static_cast<dnode*>(tail);
}
virtual void print(){}
friend class DLLIterator;
};
class DLLIterator
{
private:
ListAsDLL* dll;
public:
DLLIterator(ListAsDLL* dll)
{
this->dll = dll;
}
int getFirst()
{
return dll->head->i;
}
};
int main() {
ListAsSLL* dll = new ListAsDLL();
dll->addToBeginning(20);
DLLIterator* it = new DLLIterator((ListAsDLL*) dll);
cout<<it->getFirst()<<endl;
delete dll;
delete it;
return 0;
}
下面的代码使用了具有新的层次结构级别的装饰器模式来避免数据重复。ListAsSLL
表示可以管理单链接单元格和双链接单元格的实现。
新的类层次结构是:
List <- ListAsSSL (implementation = head, tail)
^
|- Decorator (SLL) <- PreviousDecorator (DLL)
我保留了类的原始名称,但您可以修改它们。
#include <iostream>
#include <cassert>
#include <memory>
using namespace std;
class List {
public:
virtual ~List() {}
virtual void addToBeginning(int i) {}
virtual void print() const {}
virtual int getFirst() const { assert(false); }
};
class PreviousDecorator;
class ListAsSLL : public List
{
protected:
struct node{
int i;
struct node* next;
node(int val) : i(val), next(nullptr) {}
};
node* head;
node* tail;
int listSize;
friend class PreviousDecorator;
public:
ListAsSLL()
{
head = 0;
tail = 0;
listSize = 0;
}
virtual ~ListAsSLL()
{ node* cell = head;
for (int i=0; i<listSize; ++i) {
node* temp = cell->next;
delete cell;
cell = temp;
}
}
void addToBeginning(node* anode)
{
node * temp = anode;
if(head==0){
temp->next = 0;
tail = temp;
}else if(head == tail) {
temp->next = tail;
}
else{
temp->next = head;
}
head = temp;
listSize++;
}
virtual void addToBeginning(int i) { addToBeginning(new node(i)); }
virtual void print() const
{
node* temp = head;
for (int i = 0; i < listSize; ++i) {
cout<<temp->i<<" "<<endl;
temp = temp->next;
}
}
virtual int getFirst() const { assert(head); return head->i; }
};
class Decorator : public List
{
private:
std::unique_ptr<ListAsSLL> list;
protected:
ListAsSLL& getImplementation() { return *list; }
public:
Decorator(ListAsSLL* l) : list(l) {}
virtual void addToBeginning(int i)
{
list->addToBeginning(i);
}
virtual void print() const
{
list->print();
}
virtual int getFirst() const { return list->getFirst(); }
};
class DLLIterator;
class PreviousDecorator : public Decorator
{
protected:
struct dnode : public ListAsSLL::node
{
node* prev;
dnode(int val) : node(val), prev(nullptr) {}
};
public:
PreviousDecorator(ListAsSLL* l) : Decorator(l) {}
virtual void addToBeginning(int i)
{ dnode* anode = new dnode(i);
getImplementation().addToBeginning(anode);
anode->prev = static_cast<dnode*>(getImplementation().tail);
getImplementation().tail->next = anode;
}
friend class DLLIterator;
};
class DLLIterator
{
private:
PreviousDecorator* dll;
public:
DLLIterator(PreviousDecorator* dll)
{
this->dll = dll;
}
int getFirst() const
{
return dll->getFirst();
}
};
int main() {
PreviousDecorator* dll = new PreviousDecorator(new ListAsSLL());
dll->addToBeginning(20);
cout<<dll->getFirst()<<endl;
delete dll;
return 0;
}
相关文章:
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 多方面迭代器的良好设计模式?
- 如何使用迭代器设计模式为 C++ 中的包装容器类提供多个迭代器?
- 设计具有两个指向嵌套对象的指针的迭代器
- 迭代器模式示例在 C++ 中给出错误
- std::迭代器是否可以检查该迭代器上是否存在下一个元素?(此设计受到家庭作业的限制)
- 寻找Boost转换迭代器的复合特征模式
- 可能返回值也可能不返回值的函数的迭代器缩减器模式
- 哪些因素使迭代器在调试模式下如此缓慢 (VC++ 2012)
- 未能在复合/迭代器设计模式中看到真正的价值
- 在Release模式(c++)下对迭代器进行绑定检查
- 如何在使用装饰器和迭代器设计模式时声明友类
- c++中的迭代器类设计
- 并行libstdc++模式,不使用迭代器的并行for_each算法
- 游标vs迭代器模式
- Visual C++,使用相同迭代器名称的多个for循环,在调试模式下在范围外可见
- 为基类设计基迭代器