我无法理解导致 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;
}
正如预期的那样,它的输出是“Derived”。
如果我们删除 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;
}
我对此的理解是,拥有一个虚函数会导致编译器向对象添加一个 vptr,该对象指向 vtable。vtable 包含要调用的正确函数的地址 (Derived::f()) - (以及对象的类型信息?)
现在是有趣的部分 - 与 C# 的比较。在这里,“Base”和“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# 如何正确识别对象的类型?