2

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

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 构造函数即可成功。方法甚至不是静态函数,这是怎么回事?

4

3 回答 3

4

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

于 2012-08-27T23:34:20.560 回答
2

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

但是,无论哪种情况,您都在调用未定义的行为,而我上面解释的只是一个实现细节,可能与其他实现有所不同。

于 2012-08-27T23:37:38.657 回答
-1

未定义的行为。您的代码违反了严格的别名,即使您的实现存在错误并且在应该(或者如果您将其更改为或强制转换)时dynamic_cast 没有返回 NULL以及通过尝试执行此功能而产生的一堆其他卑鄙的东西。你观察到的输出是无关紧要的。staticreinterpret

于 2012-08-27T23:35:58.950 回答