C++ 向下广播共享\u ptr<;基地>;至共享\u ptr<;派生>;?
更新:本例中的共享\u ptr与Boost中的类似,但它不支持共享\u多态\u向下转换(或者动态\u指针\u转换或静态\u指针\u转换) 我正在尝试初始化指向派生类的共享指针,但不会丢失引用计数:C++ 向下广播共享\u ptr<;基地>;至共享\u ptr<;派生>;?,c++,gcc,boost,C++,Gcc,Boost,更新:本例中的共享\u ptr与Boost中的类似,但它不支持共享\u多态\u向下转换(或者动态\u指针\u转换或静态\u指针\u转换) 我正在尝试初始化指向派生类的共享指针,但不会丢失引用计数: struct Base { }; struct Derived : public Base { }; shared_ptr<Base> base(new Base()); shared_ptr<Derived> derived; // error: invalid conve
struct Base { };
struct Derived : public Base { };
shared_ptr<Base> base(new Base());
shared_ptr<Derived> derived;
// error: invalid conversion from 'Base* const' to 'Derived*'
derived = base;
struct Base{};
派生结构:公共基{};
共享的ptr基(新基());
共享ptr派生;
//错误:从“基本*常量”到“派生*”的转换无效
衍生=基础;
到目前为止,一切顺利。我没想到C++会将Basic隐式转换成派生的*。但是,我确实需要代码所表示的功能(即,在向下转换基指针时保持引用计数)。我的第一个想法是在Base中提供一个cast操作符,这样就可以进行到派生的隐式转换(对于学究:我会检查向下转换是否有效,不用担心):
struct Base{
算子导出*();
}
// ...
Base::运算符派生*(){
返回下掷(本);
}
嗯,这没用。编译器似乎完全忽略了我的类型转换操作符。有没有办法让共享的ptr任务生效?额外要点:什么类型的
Base*const
<代码>常数基*我明白,但是基*常数
?在本例中,const
指的是什么?我假设您使用的是boost::shared\u ptr
。。。我想你想要或共享\u多态\u向下播放
但是,这些需要多态类型
什么类型的Base*const
<代码>常数基*
我明白,但是基*常数
?在这种情况下,const
指的是什么
const Base*
是指向常量Base
的可变指针
Base const*
是指向常量Base
的可变指针
Base*const
是指向可变Base
的常量指针
Base const*const
是指向常量Base
的常量指针
下面是一个简单的例子:
struct Base { virtual ~Base() { } }; // dynamic casts require polymorphic types
struct Derived : public Base { };
boost::shared_ptr<Base> base(new Base());
boost::shared_ptr<Derived> derived;
derived = boost::static_pointer_cast<Derived>(base);
derived = boost::dynamic_pointer_cast<Derived>(base);
derived = boost::shared_polymorphic_downcast<Derived>(base);
struct Base{virtual~Base(){};//动态强制转换需要多态类型
派生结构:公共基{};
boost::shared_ptr base(new base());
boost::共享的ptr派生;
派生=boost::静态指针转换(基本);
派生=boost::动态指针转换(基本);
派生=boost::共享\u多态\u向下广播(基本);
我不确定您的示例是否有意创建基类型的实例并对其进行强制转换,但它很好地说明了这一区别
static\u pointer\u cast
将“直接执行”。这将导致未定义的行为(指向Base
分配和初始化的内存的派生*
),并可能导致崩溃或更糟的情况。base
上的参考计数将增加
动态指针\u转换
将导致空指针。base
上的参考计数将保持不变
shared\u polymorphic\u downcast
将具有与静态强制转换相同的结果,但将触发断言,而不是看似成功并导致未定义的行为。base
上的参考计数将增加
见:
有时,决定是使用静态强制转换
还是动态强制转换
有点困难,您希望能够同时使用这两个世界。众所周知,动态_-cast有运行时开销,但更安全,而静态_-cast根本没有开销,但可能会无声地失败。如果您可以在调试版本中使用shared\u dynamic\u cast
,在发布版本中使用shared\u static\u cast
,那该有多好。嗯,这样一个东西已经可以使用了,叫做shared\u polymorphic\u downcast
您可以使用dynamic\u pointer\u cast
。它由std::shared\u ptr
支持
std::shared_ptr<Base> base (new Derived());
std::shared_ptr<Derived> derived =
std::dynamic_pointer_cast<Derived> (base);
std::shared_ptr base(新派生的());
std::共享的ptr派生=
std::动态指针投射(基础);
文件:
另外,我不建议在基类中使用cast操作符。像这样的隐式强制转换可能成为bug和错误的来源
-更新:如果类型不是多态的,可以使用std::static\u pointer\u cast
。如果有人使用boost::shared\u ptr…
这就是您如何向下转换到派生的Boost shared_ptr的方法。假设派生继承自基
boost::shared_ptr<Base> bS;
bS.reset(new Derived());
boost::shared_ptr<Derived> dS = boost::dynamic_pointer_cast<Derived,Base>(bS);
std::cout << "DerivedSPtr is: " << std::boolalpha << (dS.get() != 0) << std::endl;
boost::共享的;
重置(新派生的());
boost::shared_ptr dS=boost::dynamic_pointer_cast(bS);
std::cout为什么需要一个共享的\u ptr而不是共享的\u ptr?因为我想访问派生的、不在Base中的功能,而不需要克隆对象(我想要一个由两个共享指针引用的单个对象)。顺便问一下,为什么cast操作符不起作用?不幸的是,您的解决方案依赖于Boost功能,而我们正在使用的特定shared_ptr实现故意将其排除在外(不要问为什么)。至于const解释,它现在更有意义了。除了实现其他共享ptr
构造函数(使用静态\u cast\u标记
和动态\u cast\u标记
)之外,没有什么可以做的。在共享\u ptr
之外执行的任何操作都将无法管理引用计数。-在“完美”的OO设计中,您可以始终使用基类型,并且不需要知道或关心派生类型是什么,因为它的所有功能都是通过基类接口公开的。也许你需要重新思考为什么你首先要向下转换。Tim Sylvester:但是,C++不是一个“完美”的面向对象语言!向下转换在一种非完美的OO语言中占有一席之地我从第一行就不明白他没有使用std::shared\u ptr
。但从第一个答案的评论来看,我
boost::shared_ptr<Base> bS;
bS.reset(new Derived());
boost::shared_ptr<Derived> dS = boost::dynamic_pointer_cast<Derived,Base>(bS);
std::cout << "DerivedSPtr is: " << std::boolalpha << (dS.get() != 0) << std::endl;