C++ 我如何形成对非最终类的“最终”引用?

C++ 我如何形成对非最终类的“最终”引用?,c++,c++11,inheritance,polymorphism,final,C++,C++11,Inheritance,Polymorphism,Final,final是一个很好的关键词。它允许我阻止类的继承。它还允许编译器在调用虚拟函数或访问虚拟基时跳过运行时调度机制 假设现在我有一些非final类T,带有虚拟函数和/或基类。还假设我有一个对这个类的实例的引用我如何告诉编译器这个特定的引用是完全派生的完整对象,而不是派生类型更高的基子对象? 我的动机是像optional和vector这样的类。如果我调用optional::operator*(),我会得到一个T&。然而,我可以肯定地知道,这个引用实际上是一个T,而不是其他派生对象。这同样适用于vec

final
是一个很好的关键词。它允许我阻止类的继承。它还允许编译器在调用虚拟函数或访问虚拟基时跳过运行时调度机制

假设现在我有一些非
final
T
,带有虚拟函数和/或基类。还假设我有一个对这个类的实例的引用我如何告诉编译器这个特定的引用是完全派生的完整对象,而不是派生类型更高的基子对象?

我的动机是像
optional
vector
这样的类。如果我调用
optional::operator*()
,我会得到一个
T&
。然而,我可以肯定地知道,这个引用实际上是一个
T
,而不是其他派生对象。这同样适用于
vector
以及我访问其元素的所有方法


我认为,在这种情况下,跳过动态调度是一个很好的优化,尤其是在调试模式下,并且编译器不够聪明,无法查看
可选
向量
实现并对调用进行设备化。

正式地说,您可以这样做:

void final(A &a) {
  static_cast<A*>(dynamic_cast<void*>(&a))->foo();
}
void final(A&A){
静态_cast(动态_cast(&a))->foo();
}
dynamic\u cast
返回指向最派生类型的指针(并且
static\u cast
from
void*
无法选择多态基类),因此编译器可以知道正在调用
a::foo
。然而,编译器似乎没有利用这些信息;它们甚至生成明显的额外指令来实际执行动态强制转换(即使如果失败,它当然是未定义的行为)


当然,只要冗长性和泛型性允许,您就可以通过实际编写
a.a::foo()
来实现自己的虚拟化。

像这样的“伟大的优化”通常不会带来太大的代价,因为它会降低代码的可读性,并且不会在执行时间上产生实际差异。这里只是吹毛求疵,但
final
(以及
override
)不是真正的关键字。它们是仅在某些上下文中才能识别的特殊标识符。名为
final
的函数完全有效。如果它是成员函数,您甚至可以将其标记为
final
void final()final;
:)您甚至可以设计一个场景,其中
final()final有效。正确的方法是标记您的
T
class
final
。你为什么不那样做?您可以确定
T&
实际上是对编译器强制执行的具体
T
的引用。如果有人将你的
T
子类化,而你的“确定性”就消失了,那么用任何其他方式做这件事都只是自找麻烦。更不用说编译器在识别引用的具体类型和跳过虚拟发送方面可能比您想象的更聪明……您是在谈论单个翻译单元中的所有代码吗?或者函数的实现是在一个不同于可选的翻译单元中引用吗?@Nicolas:我不是依赖于“完全定义”,而是依赖于相似性条款;尽管如此,您仍然是正确的,因为可能存在多个重叠(概念上的)
T[1]
对象。即使使用
&a+2
(在没有真正的支持数组的情况下,这本身就是未定义的行为!),Clang和GCC也不会做任何事情。同时,我将使用
dynamic_cast
技巧;派生结构:祖先,A{};导出d;最后(d)这都是完全定义的,但是动态/静态强制转换产生的
a&
与传入的不同。@Filipp:我想你对优化有一点看法,但确切的情况是不明确的。