c – 动态演员和静态演员的奇怪行为

该程序没有任何异常.你能解释为什么动态演员和静态演员会成功吗?以及C如何设法解决所需的虚拟功能?

class Shape 
    {
    private :
        string helperFunction();

    public : 
        virtual void draw() = 0;
        virtual void type();
    };

void Shape::type()
    {
    cout << "Shape Type";
    }

// ----------------------------------------------------------------------------

class Circle : public Shape
    {
    private: 
    string circlething;

    public :
        virtual void draw();
        virtual void type();
        void CircleFunction();
    };

void Circle::draw()
    {
    cout <<"Circle Draw" << endl;
    }

void Circle::type()
    {
    cout <<"Circle Type" << endl;
    }

void Circle::CircleFunction()
    {
    circlething = "Circle Thing";
    cout << circlething;
    cout << "Circle Function" << endl;
    }


class Square : public Shape
    {
    private :
        string  squarething;
    public :
        virtual void draw();
        virtual void type();
        void SquareFunction();
    };

void Square::draw()
    {
    cout <<"Square Draw" << endl;
    }

void Square::type()
    {
    cout <<"Square Type" << endl;
    }

void Square::SquareFunction()
    {
    squarething = "Square Thing";
    cout << squarething;
    cout << "Square Function" << endl;
    }
// ----------------------------------------------------------------------------


int _tmain(int argc, _TCHAR* argv[])
    {
    vector<Shape *> shapes;
    Circle circle;
    Square square;
    shapes.push_back(&circle);
    shapes.push_back(&square);

    vector<Shape *>::const_iterator i;

    for (i = shapes.begin(); i < shapes.end(); ++i)
        {

        cout << "\n*** Simple Type ***\n" << endl;
        (*i)->type();
        (*i)->draw();

        cout << "---Static Cast Circle--" << endl;
        Circle* circle = static_cast<Circle*>(*i);
        circle->type();
        circle->draw();
        circle->CircleFunction();

        cout << "---Static Cast Square--" << endl;
        Square* square = static_cast<Square*>(*i);
        square->type();
        square->draw();
        square->SquareFunction();

        cout << "---Static Cast Circle to Shape --" << endl;
        Shape* shape1 = static_cast<Shape*> (circle);
        shape1->type();
        shape1->draw();

        cout << "--- Dynamic Cast Circle to Shape --" << endl;
        Shape* shape2 = dynamic_cast<Shape*> (circle);
        shape2->type();
        shape2->draw();

        cout << "--- Static Cast Square to Shape --" << endl;
        Shape* shape3 = static_cast<Shape*> (square);
        shape3->type();
        shape3->draw();

        cout << "--- Dynamic Cast Square to Shape --" << endl;
        Shape* shape4 = dynamic_cast<Shape*> (square);
        shape4->type();
        shape4->draw();

        }
    int x;
    cin >> x;
    return 0;
    }
让我们从为什么不抛出任何异常开始,因为它非常简单:当您尝试转换引用类型时,dynamic_cast会抛出异常,但它会失败.在指针上使用dynamic_cast时,如果成功则返回指针,如果指针失败则返回空指针.

至于为什么你从来没有得到失败的演员表,你的所有dynamic_cast都在层次结构中,以产生一个Shape *.由于所讨论的所有对象都是从Shape派生的,因此总是会成功 – 实际上,转换可以隐式完成.

为了演示dynamic_cast的真正意图,让我们编写一些略有不同的代码:

#include <iostream>
#include <vector>

using namespace std;

class Shape {
public : 
    virtual void draw() = 0;
};

class Circle : public Shape
{
public :
    virtual void draw() { cout << "Circle Draw\n"; }
    void circlefunc() { cout << "circle func\n"; }
};

class Square : public Shape
{
public :
    virtual void draw() { cout << "Square Draw\n"; }
    void squarefunc() { cout << "Square Func\n"; }
};

int main() {
    vector<Shape *> shapes;
    Circle circle;
    Square square;
    shapes.push_back(&circle); // implicit conversion from Circle * to Shape *
    shapes.push_back(&square); // implicit conversion from Square * to Shape *

    Circle *c;
    Square *s;
    for (int i=0; i<shapes.size(); i++) {
        shapes[i]->draw(); // draw polymorphically
        if (c = dynamic_cast<Circle *>(shapes[i])) // try to cast to Circle *
            c->circlefunc();               // if it worked, invoke circlefunc
        else if (s = dynamic_cast<Square *>(shapes[i])) // likewise for square
            s->squarefunc();
    }
    return 0;
}

这次我们使用dynamic_cast从Shape *到Square *或Circle *.当且仅当指针对象的动态类型是该类型时,这将成功.否则它将产生一个空指针.当且仅当我们获得非空指针时,我们才调用该特定类型的成员函数.

总结:当您有一个指向派生对象的指针/引用时,您可以隐式转换为指向基类的指针/引用.您不需要dynamic_cast(或任何显式的强制转换)因为这总是安全的.

当您从指针/引用转换为base以获取指向派生的指针/引用时,您通常需要使用dynamic_cast.这将基于指针对象的实际类型(即,动态类型)是否是期望目标(或其基础)而成功/失败.在这种情况下,根据您是使用指针还是引用,失败的信号会有所不同.作为参考,失败将引发异常.对于指针,失败将产生空指针.

相关文章
相关标签/搜索