c++ - 带私有(private)构造函数的 vector <class>

标签 c++ vector containers private

我有以下情况:类NoEntry包含外界可以检查的数据,但外界不允许以任何方式创建这些对象。这样的类看起来像这样:

#ifndef INCLUDED_NOENTRY_
#define INCLUDED_NOENTRY_

#include <string>

class NoEntry
{
    std::string d_name;
    size_t d_area = 0;
    size_t d_date = 0;

    public:
        std::string const &name() const;
        size_t area() const;
        size_t date() const;

    private:
        NoEntry(NoEntry const &other) = default;
        NoEntry() = default;
        NoEntry(std::string const &name, size_t area, size_t date);
};

#endif

使用 NoEntry 对象是某些类的特权,这些类被声明为 NoEntry 的友元。所以该类包含友元声明:

#ifndef INCLUDED_NOENTRY_
#define INCLUDED_NOENTRY_

#include <string>

class NoEntry
{
    friend class PrivilegedOne;
    friend class PrivilegedTwo;

    std::string d_name;
    size_t d_area = 0;
    size_t d_date = 0;

    public:
        std::string const &name() const;
        size_t area() const;
        size_t date() const;

    private:
        NoEntry(NoEntry const &other) = default;
        NoEntry() = default;
        NoEntry(std::string const &name, size_t area, size_t date);
};

#endif

我设计了以下 PrivilegedOne 界面:

#ifndef INCLUDED_PRIVILEGEDONE_
#define INCLUDED_PRIVILEGEDONE_

#include <iosfwd>
#include <vector>

#include "../noentry/noentry.h"

class PrivilegedOne
{
    std::vector<NoEntry> d_noEntry;

    public:
        PrivilegedOne(std::string const &fname);

    private:
        NoEntry nextEntry(std::istream &in);    // empty name: all were read
};

#endif

它的成员nextEntry是一个简单的成员:它从文件中读取数据,并返回一个NoEntry对象。

//#define XERR
#include "privilegedone.ih"

NoEntry PrivilegedOne::nextEntry(istream &in)
{
    NoEntry ret;

    in >> ret.d_name >> ret.d_area >> ret.d_date;

    if (not in)                         // no more NoEntries: ensure
        ret.d_name.clear();             // that d_name is empty

    return ret;
}

PrvilegedOne 的构造函数必须读取所有 NoEntry 对象,并且必须将它们存储在 d_noEntry 中。这是它的原始实现:

//#define XERR
#include "privilegedone.ih"

PrivilegedOne::PrivilegedOne(string const &fname)
{
    ifstream in{ fname };

    while (true)
    {
        NoEntry next = nextEntry(in); 

        if (next.name().empty())
            break;

        d_noEntry.push_back(next);          // Not working
    }
}

“Notworking”注释是导致所有问题的行。

为什么该语句没有发挥其作用? 不修改 NoEntry 类中的任何内容,而仅关注 PrivilegedOne:必须做什么才能允许此类的对象在其 d_noEntry vector 中存储 NoEntry 对象?

我想我应该重新设计d_noEntry的定义。然后我只需修改带有“不工作”注释的行即可。

但我不知道如何。

最佳答案

作为@“n.1.8e9-where's-my-share m.”评论说,您无法创建可与任何可能的实现一起使用的这种类型的 std::vector。

push_back() method of std::vector接受引用,但需要将对象复制到新位置。

您可以做的是创建一个包装器和 friend class它。
实现该类如下:

#pragma once
#include "NoEntry.h"

class NoEntryWrapper {
    NoEntry content;
    friend class NoEntry;
public:
    NoEntryWrapper() = default;
    NoEntryWrapper(const NoEntryWrapper &) = default;
    NoEntryWrapper(const NoEntry & content) : content(content) {}
    NoEntry &getContent() { return content; }
};

修改NoEntry实现:

// do not include "NoEntryWrapper.h"
class NoEntryWrapper; // forward declare it

class NoEntry
{
    friend class PrivilegedOne;
    friend class PrivilegedTwo;
    friend class NoEntryWrapper; // this is new

    // ... your original code ...

    NoEntry(const NoEntryWrapper &wrapper);
    // make NoEntryWrapper implicitly convertable back to NoEntry
}

并在 .cpp 中定义新添加的构造函数文件

#include "NoEntryWrapper.h"
NoEntry::NoEntry(const NoEntryWrapper &wrapper) : NoEntry(wrapper.content) {}

并且还修改PrivilegedOne类:
替换std::vector<NoEntry> d_noEntry;std::vector<NoEntryWrapper> d_noEntry; .

您现在可以使用该 vector ,就像您所异常(exception)的那样。

示例代码:

        std::vector<NoEntryWrapper> d_noEntry;
        d_noEntry.push_back(NoEntry("test", 0, 1));
        NoEntry test = d_noEntry[0];
        std::cout << test.d_name << " " << test.d_area << std::endl;

        d_noEntry[0] = NoEntry("other", 5, 5);
        d_noEntry[0].getContent().d_name = "other (name changed)";
        // this is the only drawback - you need a getter to access it this way
        NoEntry other = d_noEntry[0];
        std::cout << other.d_name << " " << other.d_area << std::endl;

// Output:
//test 0
//other (name changed) 5

关于c++ - 带私有(private)构造函数的 vector <class>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70434845/

相关文章:

docker - 如何使apache2服务在容器重启时自动运行?

当容器 < 窗口高度时 CSS 溢出内容

c++ - 替换 shared_ptr<T> 中对对象的所有引用

c++ - 传递输入参数作为右值引用?

python - 计算两个 3D 向量之间的角度

c++ - 我应该使用简单的类还是高维矩阵?

c++ - 在我的 STL 容器映射中找不到特定键

c++ - 在 mac OS-X 多线程项目上使用 asl 布局进行日志记录

c++ - 为什么即使在包含 math.h 并使用 -lm 链接到数学库之后我仍然得到 "Undefined symbol: .sqrtf"

C++ 使用 vector 重载输出