为什么需要(为了使其编译)中间CloneImplementation
和std::static_pointer_cast
(请参见下面的 3 部分)对std::shared_ptr
使用克隆模式,而不是更接近(请参见下面的 2 部分)来使用原始指针(请参阅下面的部分1 )?因为据我所知,std::shared_ptr
具有通用的复制构造函数和通用的赋值运算符?
1.带有原始指针的克隆模式:
#include <iostream>
struct Base {
virtual Base *Clone() const {
std::cout << "Base::Clone\n";
return new Base(*this);
}
};
struct Derived : public Base {
virtual Derived *Clone() const override {
std::cout << "Derived::Clone\n";
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::Clone\n";
return std::shared_ptr< Base >(new Base(*this));
}
};
struct Derived : public Base {
virtual std::shared_ptr< Derived > Clone() const override {
std::cout << "Derived::Clone\n";
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::Clone\n";
return CloneImplementation();
}
private:
virtual std::shared_ptr< Base > CloneImplementation() const {
std::cout << "Base::CloneImplementation\n";
return std::shared_ptr< Base >(new Base(*this));
}
};
struct Derived : public Base {
std::shared_ptr< Derived > Clone() const {
std::cout << "Derived::Clone\n";
return std::static_pointer_cast< Derived >(CloneImplementation());
}
private:
virtual std::shared_ptr< Base > CloneImplementation() const override {
std::cout << "Derived::CloneImplementation\n";
return std::shared_ptr< Derived >(new Derived(*this));
}
};
int main() {
Base *b = new Derived;
b->Clone();
}
最佳答案
C++中的一般规则是,覆盖函数必须与其覆盖的函数具有相同的签名。唯一的区别是指针和引用允许协方差:如果继承的函数返回A*
或A&
,则重写器可以分别返回B*
或B&
,只要A
是B
的基类。该规则使Section 1 可以正常工作。
另一方面,std::shared_ptr<Derived>
和std::shared_ptr<Base>
是两个完全不同的类型,它们之间没有继承关系。因此,不可能从替代程序返回一个而不是另一个。 2节在概念上与尝试使用virtual int f()
覆盖std::string f() override
相同。
这就是为什么需要一些额外的机制来使智能指针行为协变的原因。您显示为部分3 的部分就是这样一种可能的机制。它是最通用的一种,但在某些情况下,也存在替代方法。例如:
struct Base {
std::shared_ptr< Base > Clone() const {
std::cout << "Base::Clone\n";
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::Clone\n";
return std::shared_ptr< Derived >(CloneImplementation());
}
private:
virtual Derived* CloneImplementation() const override {
std::cout << "Derived::CloneImplementation\n";
return new Derived(*this);
}
};
关于c++11 - C++中std::shared_ptr的克隆模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43586090/