C# vs C++ - Types, inheritance and vtable

可紊 提交于 2019-12-10 20:00:06

问题


I'm having trouble understanding what causes this difference between C++ and C#.

First we have an example in which the base class contains a virtual function.

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;
}

The output of this is, as expected, "Derived".

If we remove f(), this no longer works. The output is "Base". Example:

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;
}

My understanding of this is, that having a virtual function causes the compiler to add a vptr to the object, which points to the vtable. The vtable contains the address of the correct function to invoke (Derived::f()) - (As well as type information of the object?)

Now for the interesting part - Comparison with C#. Here, "Base" and "Derived" are basically empty classes similar to the 2nd C++ example :

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()); 
        }
}

My question is thus: Is my understanding of the C++ part correct, and how does C# manage to correctly identify the type of the object when C++ doesn't?


回答1:


It's as you say: C++ enables runtime polymorphism and type identification only whenever your class has a virtual function, which means that (in common implementations) a vptr is added to the class (this is coherent with the philosophy of C++ "you don't pay for what you don't need").

(As well as type information of the object?)

Yet, it's common to store a pointer to the RTTI record in the first slot of the vtable of a class - and I'd say that this is one of the reasons why the standard requires RTTI to work only if the class is polymorphic (although, as usual, this all is compiler-dependent).

By the way, RTTI is not necessary for virtual dispatch to work correctly, if you call a virtual function all the compiler has to do is to do a call ptr with the pointer taken from the correct slot of the vtable; the RTTI record is used only when checking the class hierarchy in dynamic_cast and when asking explicitly about the type of an object via typeid.

In C#, instead, every class is polymorphic by default and has reflection metadata associated to it, so there's no need to do anything particular to enable polymorphism/type identification.




回答2:


In C++, runtime type information only really works on types where a parent class in your hierarchy has at least one virtual function. The "vtable" pointer points to the virtual function table as well as identifies the type. (In principle, at least, I can't remember how strictly the standard specifies how virtual functions should be implemented) If there are no virtual functions at all, that information is left out for efficiency.

In C# type information is always there, virtual functions or not.




回答3:


The differences between C++ and C# are deep and vast, and this is but a footnote in the encyclopaedia of differences.

Namely, in C#, every class must inherit from Object, which has virtual functions, so C# never, ever has the case where an object has no virtual functions. C++, however, does. Commonly. So in C++ there is nowhere to put the run-time type identification information.



来源:https://stackoverflow.com/questions/9727827/c-sharp-vs-c-types-inheritance-and-vtable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!