开发者

Virtual functions - where's the pointer?

开发者 https://www.devze.com 2023-02-23 17:58 出处:网络
An example to start with. class A { public: virtual const char* GetName() { return \"A\"; } }; class B: public A

An example to start with.

class A
{
    public:
    virtual const char* GetName() { return "A"; }
};

class B: public A
{
public:
    virtual const char开发者_如何转开发* GetName() { return "B"; }
};

class C: public B
{
public:
    virtual const char* GetName() { return "C"; }
};

    class D: public C
{
public:
    virtual const char* GetName() { return "D"; }
};

int main()
{
    C cClass;
    A &rBase = cClass;
    cout << "rBase is a " << rBase.GetName() << endl;

    return 0;
}

In this particular example the output is :

rBase is a C

Here are the steps of how it works:

rBase is a pointer of type A, so it goes to class A and looks for GetName(). But GetName() is virtual there so compiler checks all classes between A and C and takes GetNAme() function from the most derived class ie C

But, my doubt is that how will the compiler know which is the child of class A and how will it be able to move to class B and so on from Parent class to child class ? A child know it's parent but the parent doesn't know it's children (I think!).

From my point of view the correct steps of execution should have been:

rBase is a pointer of type A, so it goes to class A and looks for GetName(). But GetName() is virtual there so the compiler checks what class the pointer is pointing to. C class object in this case, so goes to C class and checks if it has function GetName() so uses it. If the function was not present in C class (assume) the compiler can easily trace C's parent and check for the same and this could go on until it reaches back to A (assuming all classes except A doesn't contain GetName()).

Now, this seems a more logical method because moving backward (child to parent) in an inheritance tree seems more achievable than moving forward (parent to child).

Regards,


The 2nd algorithm you describe is "correct" in that it would effectively resolve things this way. However, the compiler uses a nice trick to fast-forward that algorithm. Basically, it uses a lookup commonly called a virtual method table, often abbreviated to "vtable".

Basically, instances of classes with virtual methods hold a pointer to their class' virtual method table. The compiler maps virtual method names to offsets in the virtual table, such that invoking a virtual table does not need a complex algorithm: all that's necessary is an array lookup followed by a call at the resulting address.


rBase is a pointer of type A, so it goes to class A and looks for GetName(). But GetName() is virtual there so compiler checks all classes between A and C and takes GetNAme() function from the most derived class ie C

No, this is not how it works. The compiler when generating the code to call virtual GetName() through pointer to A just puts something like "call the 7th entry in the virtual table associated with the object". When generating a derived class that overrides GetName(), the compiler will put its GetName() implementation at this entry in the virtual table.

This way the parent class does not need to know its children. It's the children responsibility to fill their virtual table correctly.

0

精彩评论

暂无评论...
验证码 换一张
取 消