c#和c++中虚函数情况下编译器行为的差异.这是我在一次采访中被问到的问题

Difference in Compiler Behaviour in case of VIRTUAL Functions in C# and C++. This i was asked in a Interview

本文关键字:一次 问题 函数 情况下 c++ 编译器      更新时间:2023-10-16

c++和c#中的虚函数有什么不同?基本上,我想知道在c#和c++中Vtable的表示方式有什么不同吗?编译器在c#和c++中创建V表的方式是否有任何差异?

基本上面试官想知道c#和c++的虚函数编译器的行为有什么不同。

我已经回答了这个问题,提到除了c#中没有虚析构函数之外,VTABLE中可能没有什么不同。

(1)在c#中可以从基类中选择 to override a virtual函数。基方法和派生方法可以具有相同的语法,但是派生方法必须在其前面使用关键字override才能参与多态性。

在c++中,如果在派生类中提供与基类virtual方法相同的语法方法;然后它将被自动覆盖。没有选择。

(2)简而言之,在c#中我们有abstract方法,而在c++中 virtual方法。两者可能不完全相同,但等效(如纯virtual可以具有函数体)。

(3)在c++中,我们可以选择调用virtual方法而不让它参与多态性。例如,调用一个对象,调用内部构造函数。

(4)在c++中,如果基虚方法是public,派生方法是private,那么当用基句柄(指针或引用)调用方法时,virtual机制没有区别。这意味着它们的访问说明符可以不同。


现在来到你的第二个问题 vtable是如何实现的。这不是一个真正客观的问题。因为在c++本身中,不同的供应商以不同的方式实现vtable(正如@littleadve指出的那样,它不是标准的)。所以为了面试,你可以这样回答,vtable是平台相关的。

谁说v-tables了?你为什么要假设他们的存在?

主要区别(与语法有关)是,在c++中,派生类不必知道函数在祖先类中声明为virtual,而在c#中,必须使用override关键字。

可以在c#的构造函数中调用虚函数(并通过虚拟分派机制获得预期的调用行为),但在c++中不能。

虽然不推荐

Martin的回答是正确的,但值得进一步解释。

让我们假设vtable是用于解析虚拟方法调用的机制。这将使讨论更容易。

在c++中,继承层次结构中的每个构造函数都做以下工作:

  1. 调用基类构造函数(如果有基类)
  2. 设置实例的vTable指针指向当前类的vTable。
  3. 在构造函数中显式描述的内容。

vTable指针在类初始化过程中发生变化。当每个基类构造函数被调用时,vTable"演变"成它最派生的形式。

在c#中,vTable指针只被设置一次,在调用任何构造函数代码之前。对于层次结构中的每个类构造函数,只有上面描述的第1步和第3步发生。

通过在这里做出不同的设计决策,c++和c#本质上选择了不同的、必要的缺点。

在c++中,有一个风险,一个糟糕的程序员可能会调用纯虚的(又名;"抽象")方法。当基类构造函数调用在派生类中实现的虚方法时,就会发生这种情况。c++也有被重写的虚方法可能被调用的风险。

c#做事方式中的危险更微妙,但仍然存在潜在的问题。如果基类构造函数调用虚方法,则在派生类的构造函数中完成任何初始化之前调用该方法。这可能违反了派生类作者设计的预期用法。

相关文章: