0

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

#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

4 回答 4

5

两者都是未定义行为的情况。转换b1derived*无效。

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

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

于 2013-07-26T13:02:22.913 回答
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中所述的未定义行为,并且内联成员函数内存不会像此处所述的数据成员那样存储,以确保在静态转换为派生类型之后,调用派生成员函数:

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

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

于 2013-07-26T12:59:05.867 回答
0

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

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

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

于 2013-07-26T13:01:52.597 回答
-1

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

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

于 2013-07-26T12:59:19.177 回答