代码之家  ›  专栏  ›  技术社区  ›  Johnny Pauling

在动态强制转换后调用特定的类方法-奇怪的行为

  •  2
  • Johnny Pauling  · 技术社区  · 12 年前

    这是一个与我发布的另一个问题不同的问题,我有以下代码:

    class Base
    {
    public:
        Base()
        {
    
        };
    
    
        virtual void Method()
        {
            cout << "Base Method";
        }
    };
    
    class Derived : public Base
    {
    public:
        virtual void Method()
        {
            cout << "Override Method";
        }
    };
    
    
    class Derived2 : public Derived
    {
    public:
    
        Derived2()
        {
    
            cout << "Derived2 constructor";
        }
        void Method()
        {
            cout << "Override2 Method";
        }
    };
    
    int main()
    {
    
        Base *myPointer = new Derived();
    
        dynamic_cast<Derived2*>(myPointer)->Derived2::Method();
    
        Sleep(700);
    
        delete myPointer;
    
        return 0;
    }
    

    如果我写

    dynamic_cast<Derived2*>(myPointer)->Method();
    

    出现故障(dynamic_cast返回NULL,NULL->Method()引发异常),这正是我所期望的,但如果我写

    dynamic_cast<Derived2*>(myPointer)->Derived2::Method();
    

    该函数甚至在不调用Derived2构造函数的情况下就成功了。方法甚至不是一个静态函数,这里发生了什么?

    3 回复  |  直到 12 年前
        1
  •  4
  •   David Schwartz    12 年前

    您通过在NULL指针上调用成员函数触发了未定义的行为。如果您使用 dynamic_cast ,必须在取消引用之前检查返回的指针是否为NULL,或者100%确保 从不 强制转换为不是要强制转换的对象的类型或其父对象之一的类型。

        2
  •  2
  •   Jesse Good    12 年前

    当你这样做的时候 Derived2::Method(); 你在告诉编译器该调用什么函数。这意味着它会称之为 直接地 .(此外,您的成员函数什么都不做,也不依赖于任何成员变量,因此直接调用它很容易,而且不会因为不访问任何内容而崩溃)。然而,在您的第一个示例中,因为您没有明确告诉它要调用哪个函数,所以它必须查找该函数,但由于您是在空指针上调用它,因此程序崩溃。

    然而,在任何一种情况下,您都在调用未定义的行为,而我上面解释的只是一个实现细节,这可能与其他实现不同。

        3
  •  -1
  •   Puppy    12 年前

    未定义的行为。您的代码违反了严格的别名,即使您的实现被窃听并且 dynamic_cast 没有 应返回NULL时(或将其更改为 static reinterpret casts)和一堆其他卑鄙的东西。你观察到的输出是无关紧要的。