RED*_*AIR 18 c++ copy-constructor
我经常遇到问题,我必须扩展编译器生成的复制构造函数.例:
class xyz;
class C
{
...
int a, b, c;
std::set<int> mySet;
xyz *some_private_ptr;
};
Run Code Online (Sandbox Code Playgroud)
假设,some_private_ptr只应在特定条件下复制.对于其他条件,应将其重置为NULL复制.所以我必须编写一个复制构造函数,如:
C::C(const C &other) :
a(other.a),
b(other.b),
c(other.c),
mySet(other.mySet)
{
if(CanCopy(other.some_private_ptr)) // matches condition
some_private_ptr = other.some_private_ptr;
else
some_private_ptr = NULL;
}
Run Code Online (Sandbox Code Playgroud)
问题是该类可能有许多数据成员,并且当我添加数据成员时,我很可能忘记更新复制构造函数.如果我能写的话,那将是非常好的.
C::C(const C &other) :
C::default_copy(other)
{
if(CanCopy(other.some_private_ptr)) // matches condition
some_private_ptr = other.some_private_ptr;
else
some_private_ptr = NULL;
}
Run Code Online (Sandbox Code Playgroud)
这将使我的代码更安全,更容易维护.不幸的是我不知道这种可能性.有没有?
Fre*_*urk 18
最简单的方法是引入一个基类:
class xyz;
struct CDetail {
//...
int a, b, c;
std::set<int> mySet;
xyz *some_private_ptr;
};
struct C : private CDetail {
C(C const &other)
: CDetail(other)
{
if (!CanCopy(other.some_private_ptr))
some_private_ptr = 0;
// opposite case already handled
}
};
Run Code Online (Sandbox Code Playgroud)
这是滥用继承的程度,但优于嵌套"impl"类的优点是1)您可以访问每个成员作为"名称"而不是"data.name"(减少重构时的代码更改),以及2) (虽然有时只是需要)你可以"促进"个人成员受保护或公开而不影响其他成员:
struct C : private CDetail {
protected:
using CDetail::a;
};
struct D : C {
void f() {
cout << a;
}
};
int main() {
D d;
d.f(); // D can access 'a'
cout << d.a; // main cannot access 'a'
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Nim*_*Nim 16
在您定义自己的副本ctor的那一刻,编译器不会为您生成一个.不幸的是,这意味着你必须自己做所有的腿部工作!您可以将成员分组到类中的某种impl_结构中,然后依赖于复制ctor.
例如:
class xyz;
class C
{
struct impl_
{
int a, b, c;
std::set<int> mySet;
xyz *some_private_ptr;
};
impl_ data;
};
Run Code Online (Sandbox Code Playgroud)
现在在你的副本ctor
C::C(const C &other) : data(other.data)
{
// specific stuff...
}
Run Code Online (Sandbox Code Playgroud)
GMa*_*ckG 12
这里的问题是你的班级试图做太多.无论使用的资源,或管理的资源.你不会同时做这两件事,因为你的代码会成为一堆不安全的污点.这不好.
您需要设计一个管理资源的类,该资源仅在特定条件下复制.你还没有真正扩展这些条件以及为什么它们首先出现在那里(这是一种非常奇怪的"复制"数据的方式,你确定这是最好的路线吗?),但它确实是像这样:
// pointer to your condition member (not sure if this is even needed,
// is this condition knowable via the pointer alone? you get the point)
template <typename T, typename D, class Tag = void>
class copy_conditional_ptr
{
public:
copy_conditional_ptr(bool (D::*condition)(T*) const, T* value = 0) :
mCondition(condition),
mValue(value)
{}
// here's where the unique copy-semantics go
copy_conditional_ptr(const copy_conditional_ptr& other) :
mCondition(other.mCondition),
mValue(do_copy(other.mValue) ? other.mValue : 0)
{}
// other stuff for a smart pointer,
// copy-and-swap, etc...
protected:
// protected because it's meant to be a base class
~copy_conditional_ptr()
{
// whatever
}
private:
bool do_copy(T* value) const
{
const D& self = static_cast<const D&>(*this);
return (self.*mCondition)(other.value);
}
bool (D::*mCondition)(T*) const;
T* mValue;
};
Run Code Online (Sandbox Code Playgroud)
然后你像这样使用它:
class xyz;
class C : private copy_conditional_ptr<xyz, C>
{
public:
C() :
/* others, */
copy_conditional_ptr(&C::CanCopy)
{}
private:
int a, b, c;
std::set<int> mySet;
};
Run Code Online (Sandbox Code Playgroud)
让管理层对其他同学自动化.标签是这样你可以在同一个类中有多个:
class C : private copy_conditional_ptr<xyz, C, struct C_first>,
private copy_conditional_ptr<xyz, C, struct C_second>
{
// ...
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1675 次 |
| 最近记录: |