У меня проблемы с пониманием того, что вызывает эту разницу между 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. В таблице содержится адрес правильной вызываемой функции (Derived :: f ()) - (а также информация о типе объекта?)
Теперь для интересной части - Сравнение с C #. Здесь «Base» и «Derived» - это в основном пустые классы, похожие на 2-й пример 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 ++ нет?