1

I have the following code (stolen from virtual functions and static_cast):

#include <iostream>

class Base
{
public:
   virtual void foo() { std::cout << "Base::foo() \n"; }
};

class Derived : public Base
{
public:
   virtual void foo() { std::cout << "Derived::foo() \n"; }
};

If I have:

int main()
{
   Base base;
   Derived& _1 = static_cast<Derived&>(base);
   _1.foo();
}

The print-out will be: Base::foo()

However, if I have:

int main()
{
   Base * base;
   Derived* _1 = static_cast<Derived*>(base);
   _1->foo();
}

The print-out will be: Segmentation fault: 11

Honestly, I don't quite understand both. Can somebody explain the complications between static_cast and virtual methods based on the above examples? BTW, what could I do if I want the print-out to be "Derived::foo()"?

4

4 回答 4

5

在您的第二个示例中,您出现了段错误,因为您没有实例化您的基本指针。所以没有要调用的 v-table。尝试:

Base * base = new Base();
Derived* _1 = static_cast<Derived*>(base);
_1->foo();

这将打印 Base::foo()

这个问题没有意义,因为 static_cast 不会影响 v-table。但是,这对于非虚拟函数更有意义:

class Base
{
public:
   void foo() { std::cout << "Base::foo() \n"; }
};

class Derived : public Base
{
public:
    void foo() { std::cout << "Derived::foo() \n"; }
};


int main()
{
   Base base;
   Derived& _1 = static_cast<Derived&>(base);
   _1.foo();
}

这将输出 Derived::foo()。然而,这是一个非常错误的代码,虽然它可以编译,但行为是未定义的。

于 2013-06-26T18:24:15.297 回答
5

有效static_cast的指针或引用类型根本不影响虚拟调用。虚拟调用根据对象的动态类型进行解析。static_cast指向指针或引用不会改变实际对象的动态类型。

不过,您在示例中观察到的输出无关紧要。这些例子被简单地打破了。

第一个使无效static_cast。在基础对象不是 的情况下,您不得强制转换Base &为。任何执行此类转换的尝试都会产生未定义的行为。Derived &Derived

static_cast这是引用类型向下转换的有效应用示例

int main()
{
   Derived derived;
   Base &base = derived;
   Derived& _1 = static_cast<Derived&>(base);
   _1.foo();
}

在您的第二个示例中,由于与任何强制转换或虚拟调用无关的原因,代码完全被破坏。该代码尝试操作未初始化的指针 - 行为未定义。

于 2013-06-26T18:29:11.537 回答
2

虚函数的全部目的是变量的静态类型无关紧要。编译器将查找对象本身的实际实现(通常使用隐藏在对象中的 vtable 指针)。static_cast应该没有效果。

于 2013-06-26T18:24:40.160 回答
2

在这两个示例中,行为都是未定义的。Base对象不是对象,告诉编译器Derived假装它不是对象。让代码打印出来"Derived::foo()"的方法是使用 type 的对象Derived

于 2013-06-26T18:36:46.967 回答