4

该程序运行无任何异常。你能解释一下为什么动态转换和静态转换都成功了吗?以及 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;
    }
4

4 回答 4

4

让我们从为什么它不抛出任何异常开始,因为它非常简单:当您尝试强制转换引用dynamic_cast类型时抛出异常,并且它失败了。使用on 指针时,如果成功则返回一个指针,如果失败则返回一个空指针。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 *toSquare *Circle *。当且仅当指针对象的动态类型是该类型时,这才会成功。否则它将产生一个空指针。当且仅当我们获得一个非空指针时,我们才调用该特定类型的成员函数。

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

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

于 2012-05-04T14:57:30.353 回答
3

为什么要呢?dynamic_cast如果强制转换失败,则返回NULL,它不会为指针抛出异常。

另外,除此之外,它为什么会失败?两者Square都是s CircleShape所以演员阵容很好。

由于基本的多态性,输出如您所见。你有一个Shape*指向一个Square对象或一个Circle对象的 a 。virutal函数调用从最派生的类调用被覆盖的方法。这是 OOP 的核心方面。

在大多数实现中,这是通过virtual function tables. 尽管您有一个Shape*,但该对象包含一个指向内部虚函数表的指针。因为该成员在强制转换期间没有改变,它指向 aSquare或 a的虚函数表Circle,所以调用被正确解析。

在此处输入图像描述

于 2012-05-04T14:56:15.487 回答
1

您正在使用dynamic_cast从派生类型到基类型的转换,并且没有歧义。你为什么认为它会失败?此外,使用dynamic_caston 指针不会引发异常(而是会返回NULL)。在类型引用之间进行转换时,它可能会引发异常。

static_cast的成功是因为你的简单类的构造方式。由于CircleFunction()andSquareFunction()实际上并没有尝试访问任何无效的类成员变量,因此程序能够成功运行(幸运的是),使用类型之间的错误转换static_cast不是您应该做的事情。

于 2012-05-04T14:59:15.827 回答
0

简短的回答:当您在static_cast<Square>圆形指针和static_cast<Circle>方形指针上执行操作时,您已经进入了未定义的行为。那时几乎任何事情都可能发生。

此外,当您调用 时dynamic_cast,如果您要转换为指针,它可能会失败并返回 NULL。如果您要转换为引用,它只会引发异常。此外,如果编译器在编译时知道没有歧义,则编译器可以选择用编译时强制转换替换 dynamic_cast(这里就是这种情况,因为您是从子级 -> 父级强制转换)。

你得到的输出是因为这些类彼此足够相似,虽然演员表不合法,但他们还是设法工作。鉴于未定义的行为,如果您继续进行更改,就不可能依赖它。

于 2012-05-04T15:02:13.923 回答