Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在这种情况下,如何保持良好的数据封装?_C++_Oop_Encapsulation_Class Design - Fatal编程技术网

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
调用的原因。好的,我将传递迭代器。但我必须对数据进行排序。这就是将映射转换为向量的原因。@X0R40
map
本质上是排序的。您是根据代码以外的内容进行排序的吗?在这段代码中,映射值没有理由像opp一样是指针osed为一个值。我认为您需要根据对象进行推理。
库存
是否应该进行排序,或者这是
报告
类的责任?我想打印按代码和书名排序的报告。使用向量,我使用:
排序(b->begin(),b->end(),bookCompare);
,其中
bookCompare
是我比较要排序的元素的函数。好的,我将传递迭代器。但我必须对数据进行排序。这就是将映射转换为向量的原因。@X0R40
map
本质上是排序的。您是基于代码以外的内容进行排序的吗?在这段代码中,没有理由对映射进行排序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 {...};