向下转换c ++时的错误行为

时间:2013-07-26 12:55:13

标签: c++ inheritance downcast

这是我编写的一段代码,用于查看向下转换期间的行为。

#include <iostream>
using namespace std;

class base {
public :
    void function()
    {
        cout << "\nInside class Base";
    }
};

class derived : public base {
public :
    void function()
    {
        cout << "\nInside class Derived.";
    }
};

int main()
{
    base * b1 = new base();
    base * b2 = new derived();
    derived * b3 = (derived*)b1 ;
    b1 -> function();
    b2 -> function();
    b3 -> function(); // print statement 3
    static_cast<derived*>(b2) -> function();
    static_cast<derived*>(b1) -> function(); // print statement 5
    return 0;
}

输出如下。

Inside class Base
Inside class Base
Inside class Derived.
Inside class Derived.
Inside class Derived.

我觉得print statement 3和print statement 5应该显示“Inside class base”。

有人可以解释一下我在这里可能缺少什么吗?

4 个答案:

答案 0 :(得分:5)

两者都是未定义行为的情况。将b1投射到derived*无效。

但是,如果你说base* b1 = new derived(),你会有同样的行为。由于这两个函数都没有标记virtual,因此它只在编译时检查对象类型。

所以第一种情况会打印“Inside class Base”,即使它实际上是派生指针。

答案 1 :(得分:1)

您需要将基本方法void function()定义为virtual

virtual void function()
{
    cout << "\nInside class Base";
}

,结果输出为:

Inside class Base
Inside class Derived.
Inside class Base
Inside class Derived.
Inside class Base

在OP中,第5种情况可能不是引用1中所述的未定义行为,并且内联成员函数内存不像数据成员那样存储,如here所述,确保在静态转换为派生类型之后,派生成员函数被调用:

  

任何标准转换序列(第4条)的反转都没有   包含左值到右值(4.1),数组到指针(4.2),   函数到指针(4.3),空指针(4.10),空成员指针   (4.11)或布尔(4.12)转换可以显式执行   使用static_cast。

1工作草案,编程语言C ++标准,5.2.9静态演员 - 7

答案 2 :(得分:0)

在编译时,仅根据静态类型调度函数,因为它们不是虚拟的。

print语句中的b3的静态类型是Derived *,因此是'Inside class Derived'。 Print语句5将Base *转换为Derived *,因此打印输出相同。

在Base中添加virtual to function()定义并再次检查以查看会发生什么。

答案 3 :(得分:-1)

这是预期的行为 非虚拟方法由对象的类型在编译时调用 您使用了静态强制转换,因此编译器将其视为“派生”类。

如果您将方法声明为virtual,那么它将为该函数创建一个虚拟查找表,并根据实际的运行时类型调用该方法。 / p>