![](/img/trans.png)
[英]Which is a better way - store `const reference` vs `boost::shared_ptr<Class>` as a member variable
[英]Is there a better/safe way to cast non-const reference of shared_ptr to a base class?
如果您有一个带有虚拟方法的Base类和一个实现虚拟方法的Implementation类,是否有任何方法可以将std :: shared_ptr <Implementation>&强制转换为std :: shared <Base>&? 编译器允许使用const引用,但对于非const引用,它会失败,如下面代码中的“情况A”所示。 是否有捷径可寻?
如果不是,在案例B中,我的解决方法“ questionable_cast”有多安全?
#include <iostream>
#include <memory>
class Base
{
public:
virtual void set_value(int x) = 0;
};
class Implementation : public Base
{
public:
Implementation() : m_value(0) { }
void set_value(int x) override
{
m_value = x;
}
int get_value() const
{
return m_value;
}
private:
int m_value;
};
void do_something(std::shared_ptr<Base>& base)
{
base->set_value(5);
/// Code like this makes the non-const argument necessary
base = std::make_shared<Implementation>();
}
template <class T, class U>
std::shared_ptr<T>& questionable_cast(std::shared_ptr<U>& u)
{
/// This code is here to assure the cast is allowed
std::shared_ptr<T> tmp = u;
(void)tmp;
return *reinterpret_cast<std::shared_ptr<T>*>(&u);
}
int main()
{
std::shared_ptr<Implementation> a = std::make_shared<Implementation>();
// The following line causes a compiler error:
// invalid initialization of reference of type ‘std::shared_ptr<Base>&’ ...
// do_something(a);
// do_something(std::dynamic_pointer_cast<Base>(a));
// This is the workaround
do_something(questionable_cast<Base>(a));
std::cerr << "a = " << a->get_value() << std::endl;
return 0;
}
最初问到的两个明显的解决方案:1.使do_something
对shared_ptr(或按值指定shared_ptr)进行const引用。 2.创建一个名为shared_ptr并传递对此的引用:例如
int main()
{
std::shared_ptr<Implementation> a = std::make_shared<Implementation>();
std::shared_ptr<Base> b = a; // This conversion works.
do_something(b); // Pass a reference to b instead.
return 0;
}
您的questionable_cast
函数违反了严格的别名规则,并调用了未定义的行为。 它很可能在初始测试中起作用,然后新版本的编译器将优化提高了一个等级,并且在演示过程中将失败。
要处理do_something
更改指针的情况:
int main()
{
std::shared_ptr<Implementation> a = std::make_shared<Implementation>();
std::shared_ptr<Base> b = a; // This conversion works.
do_something(b); // Pass a reference to b instead.
const auto aa = std::dynamic_pointer_cast<Implementation>(b);
if (aa)
a = aa;
else
; // Handle the error here
return 0;
}
如果do_something
保证返回相同派生类型的指针,即使它不返回相同的指针,也可以将其包装在模板函数中:
template <typename T>
void do_something_ex( std::shared_ptr<T>& a )
{
std::shared_ptr<Base> b = a;
do_something(b)
a = std::dynamic_pointer_cast<T>(b);
if (!a)
throw_or_assert;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.