具有私有构造函数和析构函数的 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 [...] ?
你不能那样做。虽然 B
是 A
的 friend
,但 std::vector
是 而不是 A
的 friend
,这意味着它无法访问 A
的 private
成员,例如构造函数,这是向量工作所必需的。
但是,如果您可以接受一些间接的、潜在的性能影响很小以及签名的更改,则可以将不起作用的 std::vector<A>
替换为有效的 std::vector<std::unique_ptr<A, deleter>>
。
重要的是要注意纯 std::unique_ptr
在这里不起作用。它与 std::vector
有类似的问题 - 它无法访问 A
的 private
析构函数。解决它的一种方法是将 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_ptr
和 std::vector
都不会构造 或 破坏你的 A
。 B
完全负责构造(new A(name, num)
)和析构(static void deleter_a(A* a) { delete a; }
)A
s.
完整 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
,只是一个间接级别。
用私有构造函数和析构函数定义 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 [...] ?
你不能那样做。虽然 B
是 A
的 friend
,但 std::vector
是 而不是 A
的 friend
,这意味着它无法访问 A
的 private
成员,例如构造函数,这是向量工作所必需的。
但是,如果您可以接受一些间接的、潜在的性能影响很小以及签名的更改,则可以将不起作用的 std::vector<A>
替换为有效的 std::vector<std::unique_ptr<A, deleter>>
。
重要的是要注意纯 std::unique_ptr
在这里不起作用。它与 std::vector
有类似的问题 - 它无法访问 A
的 private
析构函数。解决它的一种方法是将 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_ptr
和 std::vector
都不会构造 或 破坏你的 A
。 B
完全负责构造(new A(name, num)
)和析构(static void deleter_a(A* a) { delete a; }
)A
s.
完整 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
,只是一个间接级别。