C#vs C++;-类型、继承和vtable 我很难理解C++和C语言之间的差异是什么造成的。

C#vs C++;-类型、继承和vtable 我很难理解C++和C语言之间的差异是什么造成的。,c#,c++,inheritance,types,object-slicing,C#,C++,Inheritance,Types,Object Slicing,首先,我们有一个示例,其中基类包含一个虚函数 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<Bas

首先,我们有一个示例,其中基类包含一个虚函数

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;
}
类基
{
受保护的:
int super;
公众:
虚拟int f()=0;
};
派生类:公共基
{
公众:
int extraA;
int f(){return 1;}
};
int main()
{
派生*d=新派生();
std::向量v;
v、 推回(d);
对于(int i=0;iSTD::CUT< P>正如你所说:只有当你的类有一个<代码>虚拟< /C>函数时,C++才允许运行时多态性和类型标识,这意味着(在通常的实现中)将一个<代码> VPTR < /C>添加到类中(这与C++的哲学是一致的)你不为你不需要的东西付费。
(以及对象的类型信息?)

然而,在一个类的vtable的第一个插槽中存储一个指向RTTI记录的指针是很常见的——我要说,这就是为什么标准要求RTTI仅在类是多态的情况下才工作的原因之一(尽管通常,这一切都依赖于编译器)

顺便说一句,RTTI不是虚拟分派正常工作所必需的,如果您调用一个虚拟函数,编译器所要做的就是使用取自vtable的正确插槽的指针执行
call ptr
;RTTI记录仅在
dynamic_cast
中检查类层次结构和明确请求时使用通过
typeid
输出对象的类型


在C++中,默认情况下,每个类都是多态的,并且有与之相关联的反射元数据,所以不需要做任何特殊的事情来实现多态性/类型标识。在C++中,

< P>,运行时类型信息只对层次结构中的父类至少有一个虚拟函数的类型进行工作。指针指向虚拟函数表并标识类型(原则上,至少我不记得标准对虚拟函数应该如何实现的规定有多严格)。如果根本没有虚拟函数,那么为了提高效率,这些信息就被忽略了


<> p类型的信息总是存在,虚函数与否。

< P> C++与C的区别是深广的,这只是百科全书中的一个脚注。
<> P>即,在C中,每个类必须继承有虚拟函数的对象,所以C永远不存在对象没有虚拟函数的情况。C++通常是这样的。所以在C++中没有运行时类型标识信息。C#中的es:--请参阅“对象布局”一节。从对象继承与此无关,他们所做的只是确定类型信息始终可用,无论是否存在任何虚拟函数。@MattiVirkkunen:唯一可以放置该类型信息的地方是在vtable中。@DeadMG,是什么阻止您拥有vtable即使对于没有虚拟方法的类型,@ Svik:C++有一个这样做的策略会非常浪费。@ USER 120 2032这是最好的答案,在你的特定情况下,主要是因为C使用了像Matto意大利语那样的反射。
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;
}
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()); 
        }
}