2

「形状」を格納するために ptr_vector を使用しています。「円」などの派生形状クラスで埋めようとしていますが、それらをダウンキャストしようとするたびにキャストが悪くなります。

class Shape
{
public:
    virtual ~Shape() {};
    virtual void print() { std::cout << "shape" << std::endl; };
};

class Circle :
    public Shape
{
public:
    void print() { std::cout << "circle" << std::endl; };
};

int main()
{
    boost::ptr_vector<Shape> shapes;
    shapes.push_back(new Circle);

    BOOST_FOREACH(Shape shape, shapes)
    {
        Circle& tempCircle = dynamic_cast<Circle&>(shape);
        if(&tempCircle != NULL)
            tempCircle.print();
    }

    system("PAUSE");
}
4

2 に答える 2

6

問題は、あなたshapeのタイプがShapeであるオブジェクトであり、(動的) タイプが であるオブジェクトへの参照ではないことですCircle

ポリモーフィズムは、参照またはポインターでのみ機能しますオブジェクトを値として扱い、派生クラスのオブジェクトから基本クラスのオブジェクトをコピー構築または移動構築すると、得られるのはスライスです (間違いなく、必要なものではありません)。

代わりにこれを試してください:

BOOST_FOREACH(Shape& shape, shapes)
//                 ^

への参照を使用することも理にかなっていますconst。おそらく、ループ内で参照されるオブジェクトを変更するつもりはないため、次のようになります。

BOOST_FOREACH(Shape const& shape, shapes)
//                  ^^^^^^  
{
    Circle const& tempCircle = dynamic_cast<Circle const&>(shape);
    //     ^^^^^^                                  ^^^^^^

    // ...
}

また、C++11 には範囲ベースのforループがありBOOST_FOREACH、時代遅れになっていることにも注意してください。したがって、C++11 がオプションの場合、次のように記述できます。

for (auto const& shape : shapes)
{
    Circle const& tempCircle = dynamic_cast<Circle const&>(shape);
    //     ^^^^^^                                  ^^^^^^

    // ...
}

これは、仮想関数であるため、ここで動的ダウンキャストを実行する必要がないことを指摘することは理にかなっています (チャドがコメントで行っているように)。print()するとき:

shape.print();

Circle::print()によって参照されるオブジェクトShapeが のインスタンスである場合、関数呼び出しは にディスパッチされますCircle

于 2013-06-27T18:04:33.133 に答える
0

また、dynamic_cast を正しく使用していません。参照を dynamic_cast し、オブジェクトがキャスト先のクラスに実際に属していない場合、キャストは をスローしstd::bad_castます。null アドレスを持つ参照などは存在しないため、null は返されません。したがって、ここに正しい方法があります:

Circle* tempCircle = dynamic_cast<Circle*>(&shape);
if(tempCircle != NULL)
    tempCircle->print();

(実際には で参照できますが、動作が定義されていないヌル ポインターを逆参照r&r == NULLた後でのみ可能です。)

于 2013-06-27T18:29:00.253 に答える