18.9 Object slicing


https://www.learncpp.com/cpp-tutorial/object-slicing/
派生class objectを取得するためにBaseptrまたはrefを使用してきました
この場合、objectはBase prt、refタイプであるが、ソースファイルにはDerived partが存在する
virtualでこれらのセクションにアクセスできます
ただし、BaseobjectにDerived objectだけを割り当てるとどうなりますか?
int main()
{
    Derived derived{ 5 };
    Base base{ derived }; // what happens here?
    std::cout << "base is a " << base.getName() << " and has value " << base.getValue() << '\n';

    return 0;
}
Derived class objectにはbaseセクションがあります.上記の場合、baseobjectは派生オブジェクトからのみBase部分をコピーします.この現象は、Derived部分が切り取られたように見えるため、オブジェクトスライスと呼ばれます.

Slicing and functions


これらのスライスについて詳しく説明しましょう
void printName(const Base base) // note: base passed by value, not reference
{
    std::cout << "I am a " << base.getName() << '\n';
}
上記の関数を定義するとき、ここで注意したいのは、パラメータがref Baseでもポインタでもなく、通常のBaseタイプであることです.
int main()
{
    Derived d{ 5 };
    printName(d); // oops, didn't realize this was pass by value on the calling end

    return 0;
}
したがって、上記のようにDerivedタイプをパラメータに渡すと、コピー時にオブジェクトスライスが発生するのでbase.getName()呼び出しBase::getName()
関数が
void printName(const Base& base) // note: base now passed by reference
{
    std::cout << "I am a " << base.getName() << '\n';
}

int main()
{
    Derived d{ 5 };
    printName(d);

    return 0;
}
parameterがBaserefの場合
この場合、pass by refになりますので、Derivedの部分は残ります
したがって、getName()は仮想関数であるため、Derived::getName()を呼び出します.

The Frankenobject


これらのスライスは、所望の結果ではなく、予期せぬエラーを引き起こす可能性があります.
もう一つのケースを見てみましょう.
int main()
{
    Derived d1{ 5 };
    Derived d2{ 6 };
    Base& b{ d2 };

    b = d1; // this line is problematic

    return 0;
}
前の3線はまあまあだ
ただし、4番目の線分(b=d 1)では、bがd 2、すなわちd 2=d 1を有すると考えられる
ただし、operator=defaultに設定したからvirtualに設定したわけではありません.
結論d 1のBase部分だけがd 2に放射される
結果d 2はベース部分がd 1のもので、Derivedは元のd 2のそれを加えた産物です.
私たちはただ何気なくフランケンの相手を作っただけです.