我有以下问题:
我有一个应该这样做的课:
Obj o;
Obj o1(o), o1=o; // deep-copies
const Obj c(o), c=o; // deep-copies
const Obj c1(c), c1=c; // shallow-copies
Obj o2(c), o2=c; // deep-copies
如果没有继承,我怎么能这样做呢? (我的意思是我会Const_obj
从Obj
继承。)
编辑:
直接使用o.clone()
不是一个选项,因为我可以轻易地通过而不是克隆来引入错误。
编辑:
最后,使用来自Scott Meyers的 Effective C ++ 的想法,有一个适当的,完整的解决方案和惰性评估。看看下面的答案。
答案 0 :(得分:4)
不,你不能。
此外,如果有可能,我会发现真的令人困惑。只需制作适合您需求的方法,并以明确的方式命名。
答案 1 :(得分:2)
阅读Scott Meyers的 Effective C ++ 后,以下是一个解决方案:
定义一个执行惰性求值的模板(带引用计数):
class Obj : private lazy<Obj_data>{};
并且惰性存储Obj_data私有,具有受保护的访问器,一个用于修改,一个用于只读访问。
如果需要,修饰符访问器首先深度复制Obj_data
,然后将引用移交给数据。只读访问器只返回一个const引用。
总体成本是存储2个额外指针(一个用于数据,一个用于计数器)和一个计数器。
实施是这样的:
class lazy{
protected:
lazy(const lazy&obj){lazy_copy(obj);}
//(the required constructors, operator= ...)
// accessors:
const Obj_data& data() const {return *od;}
Obj_data& mod_data() {make_private(); return *od;}
private:
void lazy_copy(const lazy& obj);
void make_private(); // this does the actual deep-copy, as late as possible.
private:
counter*;
Obj_data* od;
};
因此,阅读和修改Obj
的属性
void Obj::method(){
cout << data().some_attribute; // simple read
mod_data().i = 10; // simple modify
const Obj_data& const_d = data(); // assignable for lots of read-outs
Obj_data& var_d = mod_data(); // assignable for lots of modifications.
}
请注意,您只能在data()
成员中使用const
,因为mod_data()
是该类中的非const函数,因此此解决方案完全安全且开销很小。
理论背景:问题中所需的行为是一个实现细节,与客户无关。因此我们通过私有继承解决它。
答案 2 :(得分:0)
你可以部分地使用虚拟参数:
class C {
public:
struct NonStandardCopy { };
C (const C &) {
// "ordinary" copy constructor with default behavior
}
C (const C &, NonStandardCopy) {
// "other" "copy" constructor
}
};
C c = c1; // default
C c (c1); // default
C c (c1, C::NonStandardCopy ()); // non-default
编辑:只有克隆的方法可能是你想要的(与移动语义一起,性能命中可能不会太大):
class C {
private:
struct DeepCopy { };
struct ShallowCopy { };
C (const C &) = delete;
C (const C &, DeepCopy) {
// deep copy
}
C (const C &, ShallowCopy) {
// shallow copy
}
public:
// move constructor
C (C && other) = default;
const C clone () const { // 1
// shallow copy
return C (*this, ShallowCopy ());
}
C cloneToNonConst () const { // 2
// deep copy
return C (*this, DeepCopy ());
}
C clone () { // 3
return cloneToNonConst ();
}
};
C o;
C o1 = o.clone (); // call 3
const C o2 = o1.clone (); // call 3
const C o3 = o2.clone (); // call 1
C c4 = o3.cloneToNonConst (); // call 2; o3.clone () will give error