1

首先是2个代码:

#include<iostream>
using namespace std;

class A{
  public:
     virtual void  f()
    {
      cout<<"A"<<endl;
    }
};
class B: public A{
  public:
    virtual void  f()
    {
      cout<<"B"<<endl;
    }
};
int main()
{
  A* pa=new A();
  B* pb=new B();
  A* upCastpa= static_cast<A*>(pb);
  B* downCastpb=static_cast<B*>(pa);
  upCastpa->f();
  downCastpb->f();
  return 1;
}

一个显示器

B
A

因此,我认为真正重要的是指针指向的对象。但是,如果我像这样删除虚拟表单 A::f();

#include<iostream>
using namespace std;

class A{
  public:
     void  f()
    {
      cout<<"A"<<endl;
    }
};
class B: public A{
  public:
    virtual void  f()
    {
      cout<<"B"<<endl;
    }
};
int main()
{
  A* pa=new A();
  B* pb=new B();
  A* upCastpa= static_cast<A*>(pb);
  B* downCastpb=static_cast<B*>(pa);
  upCastpa->f();
  downCastpb->f();
  return 1;
}

代码会显示一个“停止” 发生了什么?如果重要的是指针指向的对象。

它假设显示 A B 而不是损坏。

发生了什么?

我非常感谢任何建议或指导。非常感谢。

4

3 回答 3

2

不管有无virtual功能:

A* pa=new A(); 
B* downCastpb=static_cast<B*>(pa); 

导致未定义的行为

当您使用static_cast将对象强制转换为它不是的类型时,它会导致未定义的行为。一旦你的代码产生了未定义的行为,尝试为观察到的输出寻找推理是没有用的。编译器可以自由地显示任何行为、崩溃、奇怪的结果或绝对正常的工作代码。您完全受编译器的支配。

参考:

C++11 标准 5.2.9 [expr.static.cast]

如果从“pointer to ”到“pointer”的有效标准转换,“ pointer to cv1 ”类型的纯右值B,其中B是类类型,可以转换为“pointer to cv2 D ”类型的纯右值,其中D是从 派生的类如果" 存在,则 cv2 与cv1具有相同的 cv 限定或大于cv1的 cv 限定,并且 既不是 的虚拟基类,也不是 的虚拟基类的基类。空指针值转换为目标类型的空指针值。如果类型为“指向cv1的指针”的纯右值BDBBDD BBD,结果指针指向类型的封闭对象D。否则,强制转换的结果是 undefined

于 2012-10-18T14:08:43.510 回答
0

通过删除第一个virtual,您可以有效地防止它进入 vtable。这意味着 classA的 vtable 现在是空的。但是,因为类B确实有一个虚函数,所以它的 vtable 中有一个条目。

因此,当您将 an 向下转换A*为 a B*,然后f通过它调用时,调用将f在空 vtable 中查找函数。没有找到它,它会抱怨代码损坏。

实际上,在一般情况下,您的示例 1 也不起作用。它在这种特殊情况下起作用的原因是 vtable forAB完全相同。

于 2012-10-18T14:04:18.037 回答
0

这就是多态性。您应该写入virtual void f()基类 A 并写入void f()继承类 B

于 2012-10-18T14:03:02.957 回答