C#与C++——类型、继承和vtable
C# vs C++ - Types, inheritance and vtable
我很难理解C++和C#之间这种差异的原因。
首先我们有一个例子,其中基类包含一个虚拟函数。
class Base
{
protected:
int super;
public:
virtual int f() = 0;
};
class Derived : public Base
{
public:
int extraA;
int f(){ return 1; }
};
int main()
{
Derived *d = new Derived();
std::vector<Base*> v;
v.push_back(d);
for(int i=0; i < v.size() ;i++)
{
// Output "Derived"
std::cout << typeid(*v[i]).name() << std::endl;
}
return 0;
}
正如预期的那样,它的输出是"派生的"。
如果我们删除f(),这将不再有效。输出为"基本"。示例:
class Base
{
protected:
int super;
};
class Derived : public Base
{
public:
int extraA;
};
int main()
{
Derived *d = new Derived();
std::vector<Base*> v;
v.push_back(d);
for(int i=0;i<v.size();i++)
{
// Output "Base"
std::cout << typeid(*v[i]).name() << std::endl;
}
return 0;
}
我对此的理解是,拥有一个虚拟函数会导致编译器向对象添加一个指向vtable的vptr。vtable包含要调用的正确函数的地址(Derived::f())-(以及对象的类型信息?)
现在来看有趣的部分-与C#的比较。这里,"Base"answers"Derived"基本上是空类,类似于第二个C++示例:
public static void Main()
{
Derived d = new Derived();
IList<Base> v = new List<Base>();
mList.Add(d);
for (int i = 0; i < v.Count; i++)
{
// Output: "Derived"
System.Console.WriteLine(v.ElementAt(i).GetType());
}
}
因此,我的问题是:我对C++部分的理解正确吗?当C++不正确时,C#如何正确识别对象的类型?
正如您所说:只有当您的类具有virtual
函数时,C++才会启用运行时多态性和类型识别,这意味着(在常见实现中)会向该类添加vptr
(这与C++的哲学"不需要什么就不需要什么"相一致)。
(以及对象的类型信息?)
然而,在类的vtable的第一个槽中存储指向RTTI记录的指针是很常见的——我想说,这就是为什么标准要求RTTI只有在类是多态的情况下才能工作的原因之一(尽管和往常一样,这一切都依赖于编译器)。
顺便说一句,RTTI不是虚拟调度正常工作所必需的,如果你调用一个虚拟函数,编译器所要做的就是用从vtable的正确插槽中取出的指针来执行call ptr
;RTTI记录仅在检查CCD_ 4中的类层次结构时以及在经由CCD_。
相反,在C#中,默认情况下,每个类都是多态的,并有与其相关的反射元数据,因此不需要做任何特定的事情来启用多态性/类型标识。
在C++中,运行时类型信息只适用于层次结构中父类至少有一个虚拟函数的类型。"vtable"指针指向虚拟函数表并标识类型。(至少原则上,我不记得标准对虚拟功能的实现方式有多严格)如果根本没有虚拟功能,那么为了效率,这些信息就被忽略了。
在C#中,无论虚拟函数与否,类型信息总是存在的。
C++和C#之间的差异是深刻而巨大的,这只是差异百科全书中的一个脚注。
也就是说,在C#中,每个类都必须继承具有虚拟函数的Object,所以C#永远不会出现对象没有虚拟函数的情况。然而,C++确实如此。通常地因此,在C++中,没有任何地方可以放置运行时类型标识信息。
- 继承函数的重载解析
- 继承期间显示未知行为的子类
- 头文件-继承c++
- 为什么在保护模式下继承升级不起作用
- 通过继承类使用来自不同命名空间的运算符
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 混合组合和继承的C++问题
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 从类继承时,继承的类是否会通过父类重新定义继承的变量
- 虚拟继承情况下的 vtable
- 为什么虚拟继承即使不涉及虚拟功能也需要 vtable?
- VTable如何处理多个继承
- C vtable在多个继承中,指向thunk方法的指针
- C++ 继承问题:未定义对"vtable"的引用
- 对"vtable for "命名空间继承的未定义引用 对"类型信息"的未定义引用
- 对具有继承的 vtable 的未定义引用
- 使用CMake构建Qt项目并从QMainWindow继承会导致未引用的vtable错误
- C#与C++——类型、继承和vtable
- 基类中的虚拟继承和空vtable
- 在Qt中,我的类继承了带有"vtable for GameControlCenter"的QObject错误,引用自: