-2

C++ スライスの例から変更した次のコードの動作を理解するのに問題があります。

#include <stdio.h>
#include <iostream>

struct B { 
    int x; 
    B() { x = 0; } 
    virtual void foo( const char* id ) { 
        std::cout << id << ": B="  << this << ", x=" << x << std::endl; 
    } 
};

struct D1 : B  { 
    int y;
    D1() { x = 1; y = 100; } 
    virtual void foo( const char* id ) { 
        std::cout << id << ": D1=" << this << ", x=" << x << ", y=" << y << std::endl; 
    } 
} d1;

struct D2 : B  {
    int z;
    D2() { x = 2; z = 200; } 
    virtual void foo( const char* id ) { 
        std::cout << id << ": D2=" << this << ", x=" << x << ", z=" << z  << std::endl; 
    } 
} d2;

void main() {
    std::cout << "d1 = " << &d1 << std::endl;
    std::cout << "d2 = " << &d2 << std::endl;

    std::cout << "By pointer at beginning: " << std::endl;
    B* pb = &d1;
    pb->foo( "pd1" );
    pb = &d2;
    pb->foo( "pd2" );

    std::cout << "By Value: " << std::endl;
    B b = d1;
    b.foo( "d1" );
    b = d2;
    b.foo( "d2" );

    std::cout << "By pointer after by value: " << std::endl;
    pb = &d1;
    pb->foo( "pd1" );
    pb = &d2;
    pb->foo( "pd2" );

    std::cout << "By reference: " << std::endl;
    B& rb = d1;
    rb.foo( "rd1" );
    rb = d2;
    rb.foo( "rd2" );

    std::cout << "By pointer after by reference: " << std::endl;
    pb = &d1;
    pb->foo( "pd1" );
    pb = &d2;
    pb->foo( "pd2" );
}

//The result is the following:
d1 = 0115B504
d2 = 0115B510
By pointer at beginning:
pd1: D1=0115B504, x=1, y=100
pd2: D2=0115B510, x=2, z=200
By Value:
d1: B=0036FE44, x=1
d2: B=0036FE44, x=2
By pointer after by value:
pd1: D1=0115B504, x=1, y=100
pd2: D2=0115B510, x=2, z=200
By reference:
rd1: D1=0115B504, x=1, y=100
rd2: D1=0115B504, x=2, y=100
By pointer after by reference:
pd1: D1=0115B504, x=2, y=100
pd2: D2=0115B510, x=2, z=200

上記の結果から、次のことがわかります。

  • 値の割り当ては、派生した特定のメンバーを削除することにより、割り当て先 (b) にスライスの問題を引き起こしますが、割り当て元 (d1 および d2) はそのまま残します。
  • 参照代入は、派生した特定のメンバを代入しないことで代入先(rd)へのスライスが発生し、代入元(d1、d2)を部分的に変更します。

最初は、悪名高い C++ キャスト システムに気付くまで、ベースを介して別の型 (D2 から D1) への参照を割り当てることができることに驚きました。1 つの結論は、参照は初期化のみが可能であり、割り当てはできないようです。

リストを除いて、他のすべてのSTLコンテナはオブジェクトをコピーするため、ベースオブジェクトのSTLコンテナにスライスの問題があることがわかっています。ポインターを内部に保存しない限り、ベース参照用の STL コンテナーはそれほど良くないように見えます。

皆さんはこの問題にどのように対処しますか?

ありがとう!CP

4

2 に答える 2