编译器添加的优化会导致“最终”方法的不同行为

时间:2012-11-01 02:38:10

标签: c++ optimization c++11 final

struct B { 
  virtual void foo ()
  { cout << "B::foo()\n"; }
};

struct D : B { 
  void foo () //final
  { cout << "D::foo()\n"; }
};

int main ()
{
  B *pB = new B;
  D *pD = static_cast<D*>(pB);
  pB->foo();
  pD->foo();
}

输出预期行为:

B::foo()
B::foo()

如果我们将D::foo()设为最终版,那么输出结果将大不相同:

B::foo()
D::foo()

这意味着当使用声明为virtual的方法的类的指针/引用调用方法时,不会激活final功能。
这也意味着,final不仅仅是一个编译时检查,而且还有助于运行时行为。

它是所有编译器的标准行为吗?我用g ++ 4.7测试过。

修改
产生new question并澄清。结束这个问题。

3 个答案:

答案 0 :(得分:11)

D *pD = static_cast<D*>(pB);

通过此声明,您放弃了理解程序行为的权利。如果给出的static_cast实际上不是D类型或D的派生类之一,那么C ++不会要求此操作有效“T)。

所以这不是挫败你的优化,只是糟糕的代码。

dynamic_cast存在的原因;正确的dynamic_cast会很快失败,返回nullptr进行非法演员。

答案 1 :(得分:5)

您正在进入未定义行为的领域,因为您通过对不是对象的实际类型的类型的指针/引用来访问对象。

3.10 [basic.lval] p10

  

如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:

     
      
  • 对象的动态类型
  •   
  • [...]
  •   

pB的动态类型显然是Base*,但动态类型pD Base*

答案 2 :(得分:3)

您在这里调用未定义的行为。你不能随意向下转动一个指针。