私は、aが期待されるunique_ptr<Derived>
場所を使用する次のコードを書きました。unique_ptr<Base>
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;
}
そして、私の理解によればunique_ptr<Base>
、 と はunique_ptr<Derived>
無関係な型であり、unique_ptr<Derived>
実際には から派生していないため、このコードはコンパイルされないと予想しましたunique_ptr<Base>
。そのため、割り当ては機能しないはずです。
しかし、何らかの魔法のおかげでそれが機能し、なぜそれが機能するのか、あるいはそれが安全であるかどうかさえ理解できません。誰か説明してくれませんか?
ベストアンサー1
あなたが探している魔法は、変換コンストラクタ#6です。ここ:
template<class U, class E>
unique_ptr(unique_ptr<U, E> &&u) noexcept;
std::unique_ptr<T>
期限切れのオブジェクトから暗黙的にオブジェクトを構築することができます。std::unique_ptr<U>
もし(わかりやすくするために削除語は省略しています):
unique_ptr<U, E>::pointer
暗黙的に変換可能pointer
つまり、派生から基本への変換を含む暗黙的な生のポインター変換を模倣し、期待どおりの動作を安全に実行します (有効期間の観点から、基本型がポリモーフィックに削除できることを依然として保証する必要があります)。