C++ 在这种情况下,如何保持良好的数据封装?
在这个例子中,一个客户在一家商店里买了很多东西,而这个商店有关于这个客户所买东西的信息。我称之为C++ 在这种情况下,如何保持良好的数据封装?,c++,oop,encapsulation,class-design,C++,Oop,Encapsulation,Class Design,在这个例子中,一个客户在一家商店里买了很多东西,而这个商店有关于这个客户所买东西的信息。我称之为库存 商店希望为每个客户打印一份报告。在下面的代码中,main只有一个清单,仅用于示例 问题是:当我想要打印报告时,我必须从客户端获取数据,但不能丢失封装。我的意思是,我希望没有任何类可以修改清单的内容 我要做的是将地图转换成一个向量(我需要一些东西来对数据进行排序)并传递这个向量(按数字分配)。 我在类库存中分配此向量,但谁在删除 是类报告,这不是正确的做事方式,但我不知道如何在不这样做的情况下传递
库存
商店希望为每个客户打印一份报告
。在下面的代码中,main只有一个清单,仅用于示例
问题是:当我想要打印报告时,我必须从客户端获取数据,但不能丢失封装。我的意思是,我希望没有任何类可以修改清单的内容
我要做的是将地图转换成一个向量(我需要一些东西来对数据进行排序)并传递这个向量(按数字分配)。
我在类库存中分配此向量,但谁在删除
是类报告
,这不是正确的做事方式,但我不知道如何在不这样做的情况下传递这些信息
无论如何,report类可以获取指向一本书的指针,并使用其set
函数或指向其他书。同样,我不知道如何正确地做
有人能告诉我在这种情况下该怎么办吗
谢谢
抱歉,代码太长了
主要内容:
课堂报告在.h中:
class Report
{
private:
Inventory* i;
public:
Report(Inventory& i);
void generateReport();
};
cpp中的课堂报告:
Report::Report(Inventory& i)
{
this->i = &i;
}
void Report::generateReport()
{
ofstream out ("Report.txt");
out << "Books: " << endl;
vector<pair<int, Book *>> * b = i->getBooks();
for(pair<int, Book *> p : *b)
{
out << p.first << ": " << p.second.getName() << endl;
}
out << endl;
delete b;
out.close();
}
报告::报告(库存和i)
{
这个->i=&i;
}
无效报告::generateReport()
{
流出流(“Report.txt”);
out您的inventory类应具有以下接口:
class Inventory
{
private:
map<int, Book *> books;
public:
using const_iterator = std::map<int, Book*>::const_iterator;
void addBook(int code, const string& name);
const_iterator begin() const { return books.begin(); }
const_iterator end() const { return books.end(); }
};
您的inventory类应具有以下接口:
class Inventory
{
private:
map<int, Book *> books;
public:
using const_iterator = std::map<int, Book*>::const_iterator;
void addBook(int code, const string& name);
const_iterator begin() const { return books.begin(); }
const_iterator end() const { return books.end(); }
};
在您的方法中,将映射
转换为向量
的技巧只引入了一个额外的依赖性:报告必须了解库存的内部情况
我建议您采用的方法:目标是将算法(生成报告、访问者)与您探索的数据结构(库存及其项目)分离
这还可以简化清单的实现,因为您不再需要为不同种类的项目预见不同的容器(前提是它们都继承自某个公共元素基类)
关于这个模式有很多资料。我推荐你设计模式,Gamma&al中的可重用面向对象软件的元素:这是最初的教科书,猜猜看,演示代码显示了一个有定价访问者的清单;-)
根据您的问题,来说明它是如何工作的。使用您的方法,将映射
转换为向量的技巧只引入了一个额外的依赖关系:报告必须了解库存的内部情况
我建议您采用的方法:目标是将算法(生成报告、访问者)与您探索的数据结构(库存及其项目)分离
这还可以简化清单的实现,因为您不再需要为不同种类的项目预见不同的容器(前提是它们都继承自某个公共元素基类)
关于这个模式有很多资料。我推荐你设计模式,Gamma&al中的可重用面向对象软件的元素:这是最初的教科书,猜猜看,演示代码显示了一个有定价访问者的清单;-)
根据您的问题,演示它是如何工作的。C++不是Java。您应该减少(如果不是消除)所有对new
的调用。想象一下如果getBooks
(例如)如果你的当前代码太差,因为调用方必须删除结果。如果没有正确使用,任何东西都可能是有害的。同时,学习C++和java非常困难。尽管语法上有一些相似之处,但它们的语言非常不同。将C++ java C++中的代码转换为C++,不好的动作。用C++的范式重写C++代码,不要只是“转换”。这就是为什么你的设计中有“<代码>新< /Calp>调用”。C++不是Java。你应该减少,如果不消除,所有调用到<代码>新< /代码>。想象一下<代码> GooBoovis/Cuth>(例如)如果你的当前代码太差,因为调用方必须删除结果。如果没有正确使用,任何东西都可能是有害的。同时,学习C++和java非常困难。尽管语法上有一些相似之处,但它们的语言非常不同。将java中的代码转换为C++——不好的动作。C++ C++中使用C++范式重写代码,不要只是“转换”。这就是为什么您的设计中充斥着new
调用的原因。好的,我将传递迭代器。但我必须对数据进行排序。这就是将映射转换为向量的原因。@X0R40map
本质上是排序的。您是根据代码以外的内容进行排序的吗?在这段代码中,映射值没有理由像opp一样是指针osed为一个值。我认为您需要根据对象进行推理。库存
是否应该进行排序,或者这是报告
类的责任?我想打印按代码和书名排序的报告。使用向量,我使用:排序(b->begin(),b->end(),bookCompare);
,其中bookCompare
是我比较要排序的元素的函数。好的,我将传递迭代器。但我必须对数据进行排序。这就是将映射转换为向量的原因。@X0R40map
本质上是排序的。您是基于代码以外的内容进行排序的吗?在这段代码中,没有理由对映射进行排序value是指针而不是值。我认为您需要根据对象进行推理。Inventory
应该排序,还是
void Inventory::addBook(int code, const string& name)
{
books.insert(pair<int, Book *>(code, new Book(name)));
}
vector<pair<int, Book *>> * Inventory::getBooks()
{
return new vector<pair<int, Book *>>(books.begin(), books.end());
}
class Inventory
{
private:
map<int, Book *> books;
public:
using const_iterator = std::map<int, Book*>::const_iterator;
void addBook(int code, const string& name);
const_iterator begin() const { return books.begin(); }
const_iterator end() const { return books.end(); }
};
for(const auto &p : *i)
{
out << p.first << ": " << p.second.getName() << endl;
}
out << endl;
class Item { ...}; // Your object structure
class Book : public Item { ... };
class Inventory { ...};
class Visitor { ... }; // Algorithms that shall be executed on structure
class Report : public Visitor {...};