在C++中克隆 std::shared_ptr 的模式



为什么需要(为了使其编译)中间CloneImplementationstd::static_pointer_cast(请参阅下面的第3节)来使用克隆模式进行std::shared_ptr,而不是更接近(请参阅下面的第 2 节)使用原始指针(请参阅下面的第 1)?因为据我了解,std::shared_ptr有一个广义复制构造函数和一个广义赋值运算符?

1. 使用原始指针克隆模式

#include <iostream>
struct Base {
virtual Base *Clone() const {
std::cout << "Base::Clonen";
return new Base(*this);
}
};
struct Derived : public Base {
virtual Derived *Clone() const override {
std::cout << "Derived::Clonen";
return new Derived(*this);
}
};
int main() {
Base *b = new Derived;
b->Clone();
}

2. 使用共享指针克隆模式(天真尝试):

#include <iostream>
#include <memory>
struct Base {
virtual std::shared_ptr< Base > Clone() const {
std::cout << "Base::Clonen";
return std::shared_ptr< Base >(new Base(*this));
}
};
struct Derived : public Base {
virtual std::shared_ptr< Derived > Clone() const override {
std::cout << "Derived::Clonen";
return std::shared_ptr< Derived >(new Derived(*this));
}
};
int main() {
Base *b = new Derived;
b->Clone();
}

输出:

error: invalid covariant return type for 'virtual std::shared_ptr<Derived> Derived::Clone() const'
error:   overriding 'virtual std::shared_ptr<Base> Base::Clone() const'

3. 使用共享指针克隆模式

#include <iostream>
#include <memory>
struct Base {
std::shared_ptr< Base > Clone() const {
std::cout << "Base::Clonen";
return CloneImplementation();
}
private:
virtual std::shared_ptr< Base > CloneImplementation() const {
std::cout << "Base::CloneImplementationn";
return std::shared_ptr< Base >(new Base(*this));
}
};
struct Derived : public Base {
std::shared_ptr< Derived > Clone() const {
std::cout << "Derived::Clonen";
return std::static_pointer_cast< Derived >(CloneImplementation());
}
private:
virtual std::shared_ptr< Base > CloneImplementation() const override {
std::cout << "Derived::CloneImplementationn";
return std::shared_ptr< Derived >(new Derived(*this));
}
};
int main() {
Base *b = new Derived;
b->Clone();
}

C++中的一般规则是重写函数必须与它覆盖的函数具有相同的签名。唯一的区别是指针和引用上允许协方差:如果继承的函数返回A*A&,则覆盖器可以分别返回B*B&,只要AB的基类。此规则允许第1节工作。

另一方面,std::shared_ptr<Derived>std::shared_ptr<Base>是两种完全不同的类型,它们之间没有继承关系。因此,无法从覆盖程序返回一个而不是另一个。第 2节在概念上与尝试用std::string f() override覆盖virtual int f()相同。

这就是为什么需要一些额外的机制来使智能指针协同行为的原因。您作为第3节展示的就是这样一种可能的机制。这是最通用的一种,但在某些情况下,也存在替代方案。例如:

struct Base {
std::shared_ptr< Base > Clone() const {
std::cout << "Base::Clonen";
return std::shared_ptr< Base >(CloneImplementation());
}
private:
virtual Base* CloneImplementation() const {
return new Base(*this);
}
};
struct Derived : public Base {
std::shared_ptr< Derived > Clone() const {
std::cout << "Derived::Clonen";
return std::shared_ptr< Derived >(CloneImplementation());
}
private:
virtual Derived* CloneImplementation() const override {
std::cout << "Derived::CloneImplementationn";
return new Derived(*this);
}
};

相关内容

  • 没有找到相关文章

最新更新