C++返回智能指针与协变的代码错误修复咨询
C++智能指针协变克隆实现的编译错误修复
我在学习C++中返回智能指针及协变实现时遇到编译错误,原代码如下:
#include <memory> #include <iostream> class cloneable { public: virtual ~cloneable() {} std::unique_ptr<cloneable> clone() const { return std::unique_ptr<cloneable>(this->clone_impl()); } private: virtual cloneable * clone_impl() const = 0; }; /////////////////////////////////////////////////////////////////////////////// template <typename Derived, typename Base> class clone_inherit: public Base { public: std::unique_ptr<Derived> clone() const { return std::unique_ptr<Derived>(static_cast<Derived *>(this->clone_impl())); } private: virtual clone_inherit * clone_impl() const override { return new Derived(*this); // 此处报错 } }; class concrete : public clone_inherit<concrete, cloneable> { }; int main() { std::unique_ptr<concrete> c = std::make_unique<concrete>(); }
编译时出现如下错误:
/tmp/0RmVdQYjfA.cpp: In instantiation of 'clone_inherit<Derived, Base>* clone_inherit<Derived, Base>::clone_impl() const [with Derived = concrete; Base = cloneable]': /tmp/0RmVdQYjfA.cpp:30:28: required from here /tmp/0RmVdQYjfA.cpp:32:14: error: no matching function for call to 'concrete::concrete(const clone_inherit<concrete, cloneable>&)' 32 | return new Derived(*this); | ^~~~~~~~~~~~~~~~~~ /tmp/0RmVdQYjfA.cpp:37:7: note: candidate: 'constexpr concrete::concrete()' 37 | class concrete : public clone_inherit<concrete, cloneable> | ^~~~~~~~ /tmp/0RmVdQYjfA.cpp:37:7: note: candidate expects 0 arguments, 1 provided /tmp/0RmVdQYjfA.cpp:37:7: note: candidate: 'constexpr concrete::concrete(const concrete&)' /tmp/0RmVdQYjfA.cpp:37:7: note: no known conversion for argument 1 from 'const clone_inherit<concrete, cloneable>' to 'const concrete&' /tmp/0RmVdQYjfA.cpp:37:7: note: candidate: 'constexpr concrete::concrete(concrete&&)' /tmp/0RmVdQYjfA.cpp:37:7: note: no known conversion for argument 1 from 'const clone_inherit<concrete, cloneable>' to 'concrete&&'
我尝试将报错行修改为:
// return new static_cast<Derived*>(*this); 替换为 return new Derived(static_cast<const Derived&>(*this));
正确修复方法
编译错误的核心原因是:在clone_inherit<concrete, cloneable>的clone_impl函数中,*this的类型是const clone_inherit<concrete, cloneable>&,而concrete的拷贝构造函数仅接受const concrete&类型的参数。虽然concrete继承自clone_inherit<concrete, cloneable>,但编译器不会自动将基类引用隐式转换为派生类引用,必须显式指定转换。
你的尝试方向是正确的,只需确保转换的安全性即可。最终的clone_impl函数应修改为:
virtual clone_inherit * clone_impl() const override { return new Derived(static_cast<const Derived&>(*this)); }
这种静态转换是安全的,因为clone_inherit<Derived, Base>是Derived的直接基类,当前的this指针必然指向Derived类型的对象(因为concrete继承自clone_inherit<concrete, cloneable>)。
另外,也可以选择使用dynamic_cast,但在这个场景下静态转换更高效,且逻辑上完全安全。
内容的提问来源于stack exchange,提问作者GPrathap
相关产品推荐
相关产品推荐

