Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8318771
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 8, 20262026-06-08T22:05:35+00:00 2026-06-08T22:05:35+00:00

So going back to basics, I’m trying to wrap my head around vtables and

  • 0

So going back to basics, I’m trying to wrap my head around vtables and whatnot. In the following example, if I were to, say, pass a B* to some function, how does that function know to call the methods in the vtable of the C object instead of the methods from the vtable of A? Are there two, separate VTables that are passed to that object? Are interface pointers really just vtables (since interfaces, IIRC, cannot contain property declarations)?

What I’m trying to say is, up until I actually tried this code, I was under the assumption you couldn’t inherit off of more than one interface/class at a time (and that all of the interfaces had to be linear, so to speak) so that the vtable built onto itself.

If my idea of how vtables worked was correct (which I now know it is not), then passing a B* and called B::OutB() would have called A:OutA() instead (which is obviously not the case).

Can someone shed some light?

// Includes
#include <windows.h>
#include <iostream>

interface A
{
public:
    virtual void OutA() = 0;
};

interface B
{
public:
    virtual void OutB() = 0;
};

class C : public A, public B
{
public:
    void OutA();
    void OutB();
};

void C::OutA()
{
    printf("Out A\n");
}

void C::OutB()
{
    printf("Out B\n");
}

int main()
{
    C obj;
    obj.OutA();
    obj.OutB();

    A* ap = (A*)&obj;
    B* bp = (B*)&obj;

    ap->OutA();
    bp->OutB();

    system("pause");

    // Return
    return 0;
}

outputs (as expected):

Out A
Out B
Out A
Out B
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-08T22:05:37+00:00Added an answer on June 8, 2026 at 10:05 pm

    I have no idea what an interface is, because:

    • interface is not a C++ keyword;
    • there is no concept of an “interface” in C++ semantics;
    • different C++ idioms or patterns can use the word interface for different specific purposes;
    • other languages use “interface” to describe completely different entities (in Java it’s like sort of special limited base class, in O’Caml it’s used where in C++ you might use a template concept).

    But if you were writing C++ and A and B were classes, then C would contain two subobjects: A and B, and each of these subobject would have its own vtable pointer.

    When compiling C++ to C, we could have:

    #include <stdio.h>
    #include <stddef.h>
    #include <stdlib.h>
    
    const int debug = 0;
    
    void __pure_virtual_called() {
        fputs ("pure virtual function called\n", stderr);
        abort();
    }
    
    /* Translation of:
    
    class A
    {
    public:
        virtual void OutA() = 0;
    };
    */
    
    struct A;
    
    typedef struct  {
        void (*ptr__OutA) (struct A *__this);
    } vtable__A;
    
    typedef struct A {
        vtable__A *__vptr;
    } A;
    
    /* translation A::OutA() 
     * pure virtual function */
    void A__OutA (A *__this) {
         __pure_virtual_called();
    }
    
    vtable__A vtable__A__A = { .ptr__OutA = A__OutA };
    
    void A__constructor (A *__this) {
        if (debug)
            printf ("A__constructor %p\n", (void*)__this);
    
        /* dynamic type is initialised to A */
        __this->__vptr = &vtable__A__A;
    }
    
    /* Translation of:
    
    class B
    {
    public:
        virtual void OutB() = 0;
    };
    
    */
    
    struct B;
    
    typedef struct {
        void (*ptr__OutB)(struct B *__this);
    } vtable__B;
    
    typedef struct B {
        vtable__B *__vptr;
    } B;
    
    /* translation B::OutB() 
     * pure virtual function */
    void B__OutB (B *__this) {
         __pure_virtual_called();
    }
    
    vtable__B vtable__B__B = { .ptr__OutB = B__OutB };
    
    void B__constructor (B *__this) {
        if (debug)
            printf ("B__constructor %p\n", (void*)__this);
    
        /* dynamic type is initialised to B */
        __this->__vptr = &vtable__B__B;
    }
    /* Translation of:
    
    class C : public A, public B
    {
    public:
        void OutA(); // overrides A::OutA()
        void OutB(); // overrides B::OutB()
        // note :
        // no new virtual function
    };
    
    */
    
    /* no new virtual function 
     * so no specific vtable type! */
    
    typedef struct {
    /* no additional vptr, we already have 2! */
        A base__A;
        B base__B;
    } C;
    
    /******* upcasts 
     * translation of 
     * static_cast<C*> (p) 
     */
    
    /* translation of 
     * A *p;
     * static_cast<C*> (p);
     */
    C *static_cast__A__C (A *__ptr) {
        /* 
         * base__A is first member of C
         * so offsetof(C, base__A) == 0
         * can skip the pointer adjustment
         */ 
        return (C*)__ptr;
    }
    
    /* translation of 
     * B *p;
     * static_cast<C*> (p);
     */
    C *static_cast__B__C (B *__ptr) {
        /* locate enclosing C object: 
         * __base__B is not first member
         * need to adjust pointer
         */
        return (C*)((char*)__ptr - offsetof(C, base__B));
    }
    
    /* translation of virtual functions of C 
     * overriding function declarations from A
     */
    
    /* translation of C::OutA() */
    
    /* C::OutA() called from C */
    void C__OutA (C *__this) {
        printf("Out A this=%p\n", (void*)__this);
    }
    
    /* C::OutA() called from A */
    void C__A__OutA (A *__this) {
        if (debug)
                printf ("C__A__OutA %p\n", (void*)__this);
        C__OutA (static_cast__A__C (__this));
    }
    
    vtable__A vtable__A__C = { .ptr__OutA = C__A__OutA };
    
    /* translation of virtual functions of C 
     * overriding function declarations from B
     */
    
    /* translation of C::OutB() */
    
    /* C::OutB() called from C */
    void C__OutB (C *__this) {
        printf("Out B this=%p\n", (void*)__this);
    }
    
    /* C::OutB() called from B */
    void C__B__OutB (B *__this) {
        if (debug)
                printf ("C__B__OutB %p\n", (void*)__this);
        C__OutB (static_cast__B__C (__this));
    }
    
    vtable__B vtable__B__C = { .ptr__OutB = C__B__OutB };
    
    void C__constructor (C *__this) {
        if (debug)
            printf ("C__constructor %p\n", (void*)__this);
        /* construct subobjects */
        A__constructor (&__this->base__A);
        B__constructor (&__this->base__B);
    
        /* adjust dynamic type of this to C */
        __this->base__A.__vptr = &vtable__A__C;
        __this->base__B.__vptr = &vtable__B__C;
    }
    
    /* calls to C virtual functions with a C* 
     */
    
    /* translation of 
     * C *p;
     * p->OutA();
     *
     * is
     * ((A*)p)->OutA();
     *
     * because C::OutA() is overrides A::OutA()
     */
    void dyn__C__OutA (C *__this) {
        A *base_ptr__A = &__this->base__A;
        base_ptr__A->__vptr->ptr__OutA (base_ptr__A);
    }
    
    /* translation of 
    
    int main()
    {
        C obj;
        obj.OutA();
        obj.OutB();
    
        A *ap = &obj;
        B *bp = &obj;
        C *cp = &obj;
    
        ap->OutA();
        bp->OutB();
        cp->OutA();
    
        // Return
        return 0;
    }
    
     *
     */
    
    int main () {
        /* translation of:
        C obj; 
        */
        C obj;
        C__constructor (&obj);
    
        /* translation of:
        obj.OutA();
        obj.OutB();
         * obj is a locally declared object
         * so dynamic type of obj is known as C
         * can make direct call to C::OutA(), C::OutB()
         */
        C__OutA (&obj);
        C__OutB (&obj);
    
        /* dumb (zero optimisation) translation of:
        A *ap = &obj;
        B *bp = &obj;
        C *cp = &obj;
        */
        A *ap = &obj.base__A;
        B *bp = &obj.base__B;
        C *cp = &obj;
    
        /* translation of:
        ap->OutA();
        bp->OutB();
        cp->OutA();
    
        * dumb compiler = no optimisation
        * so dynamic type of *ap, *bp, *cp is unknown
        * so make "virtual" calls using vtable
        */
        ap->__vptr->ptr__OutA(ap);
        bp->__vptr->ptr__OutB(bp);
        dyn__C__OutA (cp);
    
        /* note: obj lifetime ends now
         * C has a trivial destructor 
         * so no destructor call needed
         */
    
        return 0;
    }
    

    See http://ideone.com/TioyX

    Output:

    Out A this=0xbfeee2ec
    Out B this=0xbfeee2ec
    Out A this=0xbfeee2ec
    Out B this=0xbfeee2ec
    Out A this=0xbfeee2ec
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to work my way through some frustrating encoding issues by going back
This is me going right back to basics with TDD for learning purposes. I
I'm going back to the basics here but in Lua, you can define a
I'm going back through one of my old apps (my first, actually), and am
I'm going back over an old project where I added preprocessor functionality to Essence'
How do I stop my application from going back when the user clicks on
I see a lot of debate going back and forth on which language to
I have 100+ GB of photos going back 25 years. They are arranged in
I have 51 GB of HTTP (Apache) access logs for my website going back
Not sure what's going on here, but my iPhone apps nav bar shows back

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.