C++ 向下广播共享\u ptr<;基地>;至共享\u ptr<;派生>;?

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

更新:本例中的共享\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 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;