我有一个共同的抽象超类Base
,有各种Derived
类。为方便起见,我希望能够将基类作为值进行操作,而不是通过指针进行操作。我可以通过使用in this answer描述的技术创建Wrapper
来实现此目的。 Wrapper
存储unique_ptr<Base>
并转发对该指针的方法调用,并具有允许我执行的适当构造函数
Derived derived;
Wrapper wrap = derived;
wrap.callMethodOnDerived();
因此用户可以在不考虑底层指针的情况下传递,返回和存储Wrapper
。 Base
仍然完全隐藏。
然而,当他们不需要时,最终会创建副本。即
void fun(const Wrapper&);
fun(derived); // makes copy
const Wrapper& view = derived; // makes copy
将调用Wrapper(const Derived&)
转换构造函数,然后将引用传递给它。相反,我希望创建一个指向原始对象的const Wrapper&
,而不进行复制。我怎么能这样做?
#include <memory>
using BigVal = int; // Could be some expensive-to-copy type
using namespace std;
struct Base{
Base(BigVal x) : value(x){
}
unique_ptr<Base> clone() const{
return make_unique<Base>(value);
}
BigVal getValue() const{
return value;
}
protected:
BigVal value;
};
struct Derived : public Base{
Derived(BigVal x) : Base(x){
}
};
struct Wrapper{
unique_ptr<Base> ptr_;
BigVal getValue() const{
return ptr_->getValue();
}
// Ignore missing copy/move assignment operators
Wrapper(const Wrapper& other){
ptr_ = other.ptr_->clone();
}
Wrapper(Wrapper&& other){
ptr_ = move(other.ptr_);
}
Wrapper(const Base& other){
ptr_ = other.clone();
}
Wrapper(Base&& other){
ptr_ = make_unique<Base>(std::move(other));
}
};
void constFun(const Wrapper& t){
cout<<"Const fun "<<t.getValue()<<endl;
}
int main()
{
Base b1(1);
Base b2(2);
Derived d1(3);
Wrapper w = d1; // copies
Wrapper w2 = move(w); // moves
Wrapper w3 = move(b1); // moves
// No copy, just taking a reference:
const Wrapper& w4 = w2;
constFun(w2);
// Can I avoid a copy here?
const Wrapper& w5 = b2;
constFun(b2);
}
我试图改变转换形式的构造函数
Base::operator const Wrapper& (){
// return 'view' on this object
}
但这会在执行Wrapper w = Derived();
另一种选择可能是让Wrapper
永远不会复制,除非你打电话给clone
,或者在改变时懒洋洋地复制。另一个是一个独立的WrapperView
类,用于代替const Wrapper&
。但有没有办法在分配期间正常复制,但在创建引用时却没有?如果没有,其他可能性的优缺点是什么?