c#和c++中虚函数情况下编译器行为的差异.这是我在一次采访中被问到的问题
Difference in Compiler Behaviour in case of VIRTUAL Functions in C# and C++. This i was asked in a Interview
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++中,继承层次结构中的每个构造函数都做以下工作:
- 调用基类构造函数(如果有基类)
- 设置实例的vTable指针指向当前类的vTable。
- 在构造函数中显式描述的内容。
vTable指针在类初始化过程中发生变化。当每个基类构造函数被调用时,vTable"演变"成它最派生的形式。
在c#中,vTable指针只被设置一次,在调用任何构造函数代码之前。对于层次结构中的每个类构造函数,只有上面描述的第1步和第3步发生。
通过在这里做出不同的设计决策,c++和c#本质上选择了不同的、必要的缺点。
在c++中,有一个风险,一个糟糕的程序员可能会调用纯虚的(又名;"抽象")方法。当基类构造函数调用在派生类中实现的虚方法时,就会发生这种情况。c++也有被重写的虚方法可能被调用的风险。
c#做事方式中的危险更微妙,但仍然存在潜在的问题。如果基类构造函数调用虚方法,则在派生类的构造函数中完成任何初始化之前调用该方法。这可能违反了派生类作者设计的预期用法。
- 我是否需要在下一次转移时将所有权*转移回转移队列
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 在C++中一次将矢量值写入多个文件
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 为什么 zlib 放气初始化调用一次不起作用?
- 在一次迭代中从 txt 文件中读取多行
- 为什么无论你输入什么,这"while(cin.get(str,3))"只运行一次?
- 在头文件和 cpp 文件中使用一次 #pragma 时出现结构重定义错误
- 有没有办法一次声明相同类型的多个对象,并通过一个表达式立即使用相同的右值初始化它们?
- 高级选择排序 - 在一次迭代中搜索两个元素
- (2 问题)"类"类型重新定义(即使 #pragma 一次),以及静态函数内的静态成员对象初始化?
- 使用迭代器时遇到问题,每 M 次传递一次擦除一个向量项
- C++菱形问题 - 如何仅调用一次基方法
- #pragma 一次的问题
- 在C++中一次一行地从文本文件中读取int(好的字符,然后转换)时出现问题
- C++将节点添加到链表的开头一次后失败.其他方法也有问题
- C++ SQLite 查询只工作一次。我的代码有什么问题?
- 如何使"strtok function"一次使用多个令牌字符串? 函数指针会解决这个问题吗?
- 对于原始数组和std::vector,明显没有对下标进行过一次结束的说明.这个问题已经得到了决定性的解决吗?
- c#和c++中虚函数情况下编译器行为的差异.这是我在一次采访中被问到的问题