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

I am having trouble understanding what is causing this difference between C ++ and C #.

First, we have an example where 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 result of this is, as expected, "Derived".

If we remove f (), this no longer works. Exit "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 the vptr to the object that points to the vtable. The vtable contains the address of the correct function to call (Derived :: f ()) - (as well as information about the object's type?)

Now for the fun part - Comparison with C #. Here "Base" and "Derived" are mostly empty classes, similar to the second 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()); 
        }
}

      

So my question is, do I understand the C ++ part correctly and how does C # manage to correctly identify the type of an object when C ++ doesn't work?

+3


source to share


3 answers


This is how you say: C ++ only allows runtime polymorphism and type identification when your class has a function virtual

, which means that (in common implementations) added vptr

to the class (this is consistent with the philosophy from C ++ "you don't pay for what you don't need ").

(as well as information about the type of object?)

However, it is common to store a pointer to an RTTI entry in the first vtable slot of a class - and I would 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 is all compiler-dependent ).



By the way, RTTI is not required for virtual dispatch to work properly, if you call a virtual function that the compiler must execute, do it call ptr

with a pointer taken from the correct vtable slot; the RTTI record is only used when checking the class hierarchy in dynamic_cast

and when explicitly querying the object type through typeid

.

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

+6


source


In C ++, runtime type information only really works on types where the parent class in your hierarchy has at least one virtual function. The "vtable" pointer points to the virtual function table and also defines the type. (Basically, at least I don't remember how strictly the standard specifies how virtual functions should be implemented). If there are no virtual functions at all, this information is not considered for efficiency.



C # type info always has virtual functions or not.

+3


source


The differences between C ++ and C # are deep and extensive, and this is just a footnote in the encyclopedia of differences.

Namely, in C #, every class must inherit from Object, which has virtual functions, so C # never, never has a case where an object has no virtual functions. C ++ does, however. Usually. Thus, in C ++, you do not need to specify the runtime type identification information.

+2


source







All Articles