在这种情况下如何保持良好的数据封装?

时间:2015-12-03 19:41:23

标签: c++ oop encapsulation class-design

我是c ++的新手,我正在尝试制作一个非常简单的CRUD程序。

在这个例子中,客户在商店里买了很多东西,这个商店有关于这个客户买的东西的信息。我称之为Inventory

商店想要为每个客户打印Report。在下面的代码中,main只有一个Inventory,仅用于示例。

问题是:当我想打印报告时,我必须从客户端获取数据,但不会丢失封装。我的意思是,我希望没有班级可以修改库存的内容。

我要做的是将地图转换为向量(我需要对数据进行排序)并传递此向量(以dinamically方式分配)。 我在类Inventory分配此向量但是谁正在删除 是Report类,这不是正确的做事方式,但我不知道如何在不这样做的情况下传递这些信息。

无论如何,报表类可以获取指向Book的指针,并使用其set函数或指向其他Book。同样,我不知道如何正确地做到这一点。

在这种情况下,有人可以给我一些提示吗?

感谢。

很抱歉这长码。

主:

int main(void)
{
    Inventory i;
    Report r(i);

    i.addBook("Foo Bar I");
    i.addBook("Foo Bar II");

    r.generateReport();

    return 0;
}

.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();
}

.h中的班级清单:

class Inventory 
{
private:
    map<int, Book *> books;

public:
    void addBook(int code, const string& name);
    vector<pair<int, Book *>> * getBooks();
};

.cpp中的班级清单:

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());
}

2 个答案:

答案 0 :(得分:0)

您的广告资源类应具有以下界面:

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(); }
};

没有理由将地图副本创建为矢量!这是低效的,而不是理由。

重写generateReport以使用此界面,如下所示:

for(const auto &p : *i)
{
    out << p.first << ": " << p.second.getName() << endl;
}
out << endl;

答案 1 :(得分:0)

使用您的方法,将map转换为vector的技巧只引入了一个额外的依赖:报告必须知道清单的内部。

我建议采用 vistitor design pattern 的方式:目标是将算法(生成报告,访问者)与您探索的数据结构分开(库存及其项目)。

class Item { ...};      // Your object structure 
class Book : public Item { ... }; 
class Inventory { ...}; 

class Visitor { ... };  // Algorithms that shall be executed on structure
class Report : public Visitor {...};

这也可以简化您的库存的实施,因为您不再需要为不同类型的项目预见不同的容器(前提是它们都从一些公共元素基类继承)。

Theres在这种模式上有很多文章。我建议您使用Gamma&amp; G中的设计模式,可重复使用的面向对象软件的元素。 al:它的原始教科书,并猜猜是什么,演示代码显示了一个定价访问者的库存;-)

Here a naive on-line example根据您的问题,说明它是如何工作的。