这是我编写的一段代码,用于查看向下转换期间的行为。
#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”。
有人可以解释一下我在这里可能缺少什么吗?
答案 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>