2
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 进行了测试。

编辑:产生了一个澄清
新问题。结束这个问题。

4

3 回答 3

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

有了这个声明,你就放弃了拥有理智的程序行为的权利。如果给定的内容实际上不是类型或的派生类之一(它不是),则C++不需要此操作。static_castDD

所以阻碍你的不是优化,而是糟糕的代码。

存在是有原因的dynamic_cast;一个适当的dynamic_cast人很快就会在这方面失败,返回nullptr非法演员。

于 2012-11-01T02:47:11.397 回答
5

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

3.10 [basic.lval] p10

如果程序尝试通过非下列类型之一的泛左值访问对象的存储值,则行为未定义:

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

的动态类型显然pBBase*,但动态类型仍然pD是。 Base*

于 2012-11-01T02:48:30.790 回答
3

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

于 2012-11-01T02:43:50.227 回答