You*_*008 21 c++ inheritance templates unique-ptr
我编写了以下代码,unique_ptr<Derived>其中使用了unique_ptr<Base>预期的a
class Base {
int i;
public:
Base( int i ) : i(i) {}
int getI() const { return i; }
};
class Derived : public Base {
float f;
public:
Derived( int i, float f ) : Base(i), f(f) {}
float getF() const { return f; }
};
void printBase( unique_ptr<Base> base )
{
cout << "f: " << base->getI() << endl;
}
unique_ptr<Base> makeBase()
{
return make_unique<Derived>( 2, 3.0f );
}
unique_ptr<Derived> makeDerived()
{
return make_unique<Derived>( 2, 3.0f );
}
int main( int argc, char * argv [] )
{
unique_ptr<Base> base1 = makeBase();
unique_ptr<Base> base2 = makeDerived();
printBase( make_unique<Derived>( 2, 3.0f ) );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望这段代码不会编译,因为根据我的理解unique_ptr<Base>,unique_ptr<Derived>它们是不相关的类型,并且unique_ptr<Derived>实际上不是从中派生的,unique_ptr<Base>因此赋值不起作用。
但是多亏了一些魔术,它才能起作用,而且我不知道为什么,即使这样做是安全的。有人可以解释一下吗?
Que*_*tin 25
您正在寻找的神奇之处是这里的转换构造函数#6 :
template<class U, class E>
unique_ptr(unique_ptr<U, E> &&u) noexcept;
Run Code Online (Sandbox Code Playgroud)
它允许std::unique_ptr<T>从到期std::unique_ptr<U> if隐式构造(为清楚起见,在删除器上进行光泽处理):
unique_ptr<U, E>::pointer可隐式转换为pointer
也就是说,它可以模仿隐式原始指针转换,包括派生到基数的转换,并且可以安全地执行您期望的操作(就生命周期而言,您仍然需要确保可以多态删除基类型)。
son*_*yao 13
因为std::unique_ptr有一个转换构造函数
Run Code Online (Sandbox Code Playgroud)template< class U, class E > unique_ptr( unique_ptr<U, E>&& u ) noexcept;
和
如果满足以下所有条件,则此构造方法仅参与重载解析:
a)
unique_ptr<U, E>::pointer可隐式转换为pointer...
A Derived*可以Base*隐式转换为,然后可以在这种情况下应用转换构造函数。然后std::unique_ptr<Base>可以std::unique_ptr<Derived>像原始指针一样从隐式转换a 。(请注意,由于的特性,std::unique_ptr<Derived>必须将其作为构造的右值。)std::unique_ptr<Base>std::unique_ptr
您可以隐式构造一个std::unique_ptr<T>从一个实例右值的std::unique_ptr<S>时候S可以转换为T。这是由于构造器#6 这里。在这种情况下,所有权被转移。
在您的示例中,您只有类型的右std::uinque_ptr<Derived>值(因为的返回值std::make_unique是右值),当您将其用作a时std::unique_ptr<Base>,将调用上述构造函数。std::unique_ptr<Derived>因此,所讨论的对象仅生存很短的时间,即它们被创建,然后所有权被传递给std::unique_ptr<Base>对象,该对象将被进一步使用。
| 归档时间: |
|
| 查看次数: |
998 次 |
| 最近记录: |