Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 动态强制转换和静态强制转换的奇怪行为_C++_Oop_Casting_Virtual Functions_Dynamic Cast - Fatal编程技术网

C++ 动态强制转换和静态强制转换的奇怪行为

C++ 动态强制转换和静态强制转换的奇怪行为,c++,oop,casting,virtual-functions,dynamic-cast,C++,Oop,Casting,Virtual Functions,Dynamic Cast,这个程序毫无例外地运行。你能解释一下为什么动态强制转换和静态强制转换是成功的吗?以及C++如何解决所需的虚拟函数? class Shape { private : string helperFunction(); public : virtual void draw() = 0; virtual void type(); }; void Shape::type() { cout <<

这个程序毫无例外地运行。你能解释一下为什么动态强制转换和静态强制转换是成功的吗?以及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;
    }
类形状
{
私人:
字符串helperFunction();
公众:
虚空绘制()=0;
虚空类型();
};
空心形状::类型()
{

cout为什么要这样做?
dynamic_cast
返回
NULL
如果强制转换失败,它不会为指针抛出异常

另外,撇开这一点不谈,为什么它会失败呢?
正方形
圆形
都是
形状
s。所以演员阵容很好

由于基本多态性,输出与您看到的一样。您有一个
形状*
,它指向
正方形
对象或
圆形
对象。
virutal
函数调用来自最派生类的重写方法。这是OOP的一个中心方面

在大多数实现中,这是通过
虚拟函数表
实现的。尽管您有一个
形状*
,但对象内部有一个指向虚拟函数表的指针。因为该成员在强制转换过程中没有改变,所以它指向
正方形
圆形
的虚拟函数表,因此调用正确解决了这些问题


让我们从它为什么不抛出任何异常开始,因为它非常简单:
dynamic\u cast
在您尝试抛出引用类型时抛出异常,但失败。当您对指针使用
dynamic\u cast
时,如果成功,它将返回指针,如果失败,它将返回空指针

至于为什么您从未获得失败的强制转换,您的所有
动态\u强制转换
都在层次结构上,以生成一个
形状*
。由于所有有问题的对象都是从
形状
派生的,因此这将总是成功的——事实上,转换可以隐式完成

为了演示
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;
}
#包括
#包括
使用名称空间std;
阶级形态{
公众:
虚空绘制()=0;
};
班级圈子:公共形态
{
公众:

virtual void draw(){cout您正在使用
dynamic\u cast
将派生类型转换为基类型,并且没有任何歧义。为什么您希望失败?另外,在指针上使用
dynamic\u cast
不会引发异常(相反,它将返回
NULL
)。在类型引用之间强制转换时,它可能引发异常


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

简短回答:当你在圆指针上执行
static\u cast
和在方指针上执行
static\u cast
时,你已经陷入了未定义的行为。几乎任何事情都可能发生在这一点上

此外,当您调用
dynamic_cast
时,如果您对指针进行强制转换,它可能会失败并返回NULL。它仅在您转换为引用时才会引发异常。此外,如果编译器在编译时知道不存在歧义,则可以选择用编译时强制转换替换dynamic_cast(这里就是这种情况,因为您是从child->parent进行施法的)


您得到的输出是因为这些类彼此非常相似,虽然强制转换是不合法的,但它们无论如何都能工作。鉴于未定义的行为,如果您继续进行更改,就不可能依赖于此。

请注意,OP在
中插入了一个
圆*
和一个
正方形*
ctor
,然后在迭代时将圆同时转换为
正方形*
圆形*
。因此OP将圆转换为正方形(通过共享形状基)你能解释一下为什么静态强制转换也会成功吗?@kunj2aan:
static\u cast
甚至不会试图判断你尝试的转换是否有效。在你的情况下,它可能会起作用,主要是因为你的成员函数不使用任何类数据,所以用指向它的
指针调用它们错误的数据不会造成明显的伤害/问题。嗨,我用新的成员函数修改了代码,程序仍然可以正常运行。这就是你的意思吗?