具有私有构造函数和析构函数的 class 对象的向量?

Vector of class object with private constructor and destructor?

用私有构造函数和析构函数定义 classes A(应该如此!)和 B 作为朋友 class,我如何在 B 中创建 A 对象的向量并填充它与功能 addA()。我收到错误 "error C2248: "A::~A": 无法访问在 A class" 中声明的私有成员。

class A
{
private:
    A();
    A(const std::string& name, const float& num);
    ~A();
public:
    friend class B;
private:
    std::string name_;
    float num_;
};

A::A() 
{
    name_ = "NoName";
    num_ = 0.0;
}
A::A(const std::string& name, const float& num)
{
    name_ = name;
    num_ = num;
}
A::~A()
{   
}

class B
{
public:
    B();
    ~B();
    void addA(const std::string name, const float num);
private:
    vector<A> vecA;
};

B::B() 
{
}
B::~B() 
{
}
void B::addA(const std::string name, const float num)
{
    A a(name, num);
    vecA.push_back(a);
}

int main()
{
    B b;
    b.addA("Name", 1.0);

    return 0;
}

how can I create a vector of A objects in B [...] ?

你不能那样做。虽然 BAfriend,但 std::vector 而不是 Afriend,这意味着它无法访问 Aprivate 成员,例如构造函数,这是向量工作所必需的。

但是,如果您可以接受一些间接的、潜在的性能影响很小以及签名的更改,则可以将不起作用的 std::vector<A> 替换为有效的 std::vector<std::unique_ptr<A, deleter>>

重要的是要注意纯 std::unique_ptr 在这里不起作用。它与 std::vector 有类似的问题 - 它无法访问 Aprivate 析构函数。解决它的一种方法是将 A 的构造和破坏工作完全外包给 B - 通过显式构造和破坏,即:

  • new A(name, num)
  • static void deleter_a(A* a) { delete a; }

B的范围内。

现在我们可以做:

std::vector<std::unique_ptr<A, std::function<void(A*)>>> vecA;

而不是:std::vector<A>std::vector<std::unique_ptr<A>>。这很重要 - std::unique_ptrstd::vector 都不会构造 破坏你的 AB完全负责构造(new A(name, num))和析构(static void deleter_a(A* a) { delete a; }As.

完整 B class:

class B {
public:
    B() {};  // or = default
    ~B() {}; // or = default
    void addA(const std::string name, const float num);

private:
    static void deleter_a(A* a) { delete a; }
    using deleter_a_t = void(A*);
    std::vector<std::unique_ptr<A, std::function<deleter_a_t>>> vecA;
};

void B::addA(const std::string name, const float num) {
    vecA.push_back(std::unique_ptr<A, std::function<deleter_a_t>>{
            new A(name, num), std::function<deleter_a_t>{deleter_a}
    });
}

虽然@Fureeish 有一个巧妙的解决方案,但这里有一个稍微简单的替代方案:将它包装起来。

class AccessPrivate;

class PrivStuff
{
private:
    PrivStuff() {}
    ~PrivStuff() {}
public:
    friend class AccessPrivate;

    std::string m_data{};
};

class AccessPrivate
{
public:
    AccessPrivate() = default;
    ~AccessPrivate() = default;

    PrivStuff m_priv;
};

int main(int argc, char* argv[])
{
    std::vector<AccessPrivate> myvec;
    myvec.resize(4);

    for (auto& stuff : myvec)
    {
        stuff.m_priv.m_data = "heya";
    }

}

如果您需要更复杂的东西,例如传递参数,只需向 AccessPrivate 添加等效的构造函数即可。您基本上可以像对待实际的私有 class 一样对待 AccessPrivate,只是一个间接级别。