了解虚拟功能内部 [英] Understand Virtual functions Internals

查看:59
本文介绍了了解虚拟功能内部的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是想了解虚拟fns.概念.

我知道如果我有一个虚拟fn.在基类及其覆盖的fn中.然后在派生类中基于存储在基类指针fns中的基类/派生对象的地址进行操作.将被称为.


在下面的代码中,我保留了show()fn.作为虚拟的,它用于正确地调用基类和派生类show().

但是,当我从show()中删除虚拟标签时,为什么它不调用派生的show(),尽管基类指针具有派生类对象的地址呢?

I am just trying to understand the virtual fns. concept.

I know that if I have a virtual fn. in a base class and its overridden fn. in derived class then based upon the address of base/derived object stored in the base class pointer the fns. will be called.


In the below code I had kept the show() fn. as virtual and it used to call properly the base and derived classes show().

But when I removed the virtual tag from show() then why does not it calls derived show() inspite of base class pointer having address of derived class object?

class base
{
public:
    base()
    {
        printf("Base Cons\n");
    }

    void show()
    {
        printf("Base Show\n");
    }
};

class der: public base
{
public:
    der()
    {
        printf("Der Cons\n");
    }

    void show()
    {
        printf("Der Show\n");
    }
};

void yahoo(base* bpointer)
{
    printf("Address in base pointer = %u\n",bpointer);
    bpointer->show();
}

int _tmain(int argc, _TCHAR* argv[])
{
    class base bobj, *bptr;
    class der dobj;

    bptr = & bobj;
    printf("Base obj adress = %u\n",&bobj);
    yahoo(bptr);

    bptr = &dobj;
    printf("Base obj adress = %u\n",&dobj);
    yahoo(bptr);

    return 0;
}




代码输出:




Output of code:

Base Cons
Base Cons
Der Cons
Base obj adress = 1245027
Address in base pointer = 1245027
Base Show
Base obj adress = 1245003
Address in base pointer = 1245003
Base Show

推荐答案

您需要在基类中使用关键字virtual.
如果您忽略这一点.这些功能不会被覆盖,只会被隐藏.
You need the keyword virtual in your base class.
If you omit this. The functions are not overridden only hidden.
virtual void show()



这是因为您的指针是基*,因为函数"show"不是虚拟的,因此编译器无需搜索覆盖的成员.



This is because your pointer is a base*, as the function ''show'' is not virtual, there is no need for the compiler to search for an overridden member.


的每个对象der也会自动为base类型.它继承了所有内容,但可能会重载方法.

如果show()不是虚拟的:用于访问该方法的指针的类型确定将使用该方法的重载.您使用类型为base *的指针,因此它将被称为base :: show().

如果show()是虚拟的:对象的实际类型确定将调用哪个方法,无论是否通过指向基类的指针访问它.在这种情况下,将调用der :: show().

但是,为什么对象的地址应该更改? base的对象在某个地址,der的对象在另一个地址.派生的对象可以看作是base的对象,也可以是der之一,但是它仍然在同一位置.
Every object of der also automatically is of the type base. It inherits everything, but may overload methods.

If show() is not virtual: The type of the pointer used to access the method determines which overload of the method will be used. You use a pointer of the type base*, so it will be base::show() that will be called.

If show() is virtual: The actual type of the object determines which method will be called, no matter wether you access it over a pointer to the baseclass or not. In this case der::show() would be called.

But why should the address of an object change? The object of base is at a certain address and the object of der at another one. The derived object can be seen as an object of base as well as one of der, but it still is at the same location.


从语言角度来看,虚函数允许派生类型的对象就像它们是基本类型一样被访问,并且在派生类中仍具有适当的功能.

这里的情况是所有引用都使用被声明为指向基类的指针的情况,因此,在没有virtual的情况下,仅调用基类函数就不足为奇了.

有一些魔术.为了使编译后的代码合理而又小又快速,编译器着眼于对类及其功能的了解和不了解.如果编译器可以完全解决引用类型"(指针或对象)和成员函数"(按名称/足迹)的问题,则编译器可以将整个过程优化为直接调用代码(设置"this ",然后让链接程序解析实际的代码位置.

如果成员函数是虚拟的,则它无法确切知道要直接调用哪个成员函数,因此它必须使用跳转表或通过对象本身内置的数据调度调用的向量类型.该表对于创建的每个对象都存在,因此,为了防止表过大,此处仅列出虚函数.

因此,使用虚拟方法时,您将获得通过调度表的间接引用",而如果使用虚拟方法,则将获得对已知成员函数的直接调用".

那应该可以解释您所看到的行为.
Language wise, virtual functions allow for objects of the derived type to be accessed as if they were the base type and still have the proper functions in the derived class be called.

what you have here is a case where all of your references are using pointers that are declared to be pointers to the base class so, without virtual, it''s not surprising that only base class functions are called.

There is some magic involved. In order to keep compiled code reasonably small and fast, the compiler looks at what it knows and doesn''t know about a class and its functions. If the compiler can completely resolve the issue of "reference type" (the pointer or object) and the "member function" (by name / footprint) then the compiler can optimize the whole thing into a direct call to the code (setting "this" and letting the linker resolve the actual code location).

If the member function is virtual, then it cannot know exactly which member function to call directly so it has to use a jump table or dispatch vector type of call through data built into the object itself. That table exists for every object created so, to keep the table from being overly huge, only virtual functions are listed there.

So, with virtual, you get "indirect references through a dispatch table", without virtual, you get "direct calls to known member functions".

That should explain the behavior you see.


这篇关于了解虚拟功能内部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆