Diamond shaped polymorphic Inheritance: sizeof Most derived Class












4















I understand that the Diamond shaped inheritance causes ambiguity and it can be avoided by using inheritance through virtual Base Classes, the question is not about it. The question is about sizeof the most derived class in a diamond shaped hierarchy when the classes are polymorphic. Here is a sample code and the sample output:



#include<iostream>

using namespace std;

class Base
{
public:
virtual void doSomething(){}
};

class Derived1:public virtual Base
{
public:
virtual void doSomething(){}
};

class Derived2:public virtual Base
{
public:
virtual void doSomething(){}
};

class Derived3:public Derived1,public Derived2
{
public:
virtual void doSomething(){}
};

int main()
{
Base obj;
Derived1 objDerived1;
Derived2 objDerived2;
Derived3 objDerived3;

cout<<"n Size of Base: "<<sizeof(obj);
cout<<"n Size of Derived1: "<<sizeof(objDerived1);
cout<<"n Size of Derived2: "<<sizeof(objDerived2);
cout<<"n Size of Derived3: "<<sizeof(objDerived3);

return 0;
}


The output i get is:



 Size of Base: 4
Size of Derived1: 4
Size of Derived2: 4
Size of Derived3: 8


As I understand Base contains a virtual member function and hence,

sizeof Base = size of vptr = 4 on this environment



Similar is the case Derived1 & Derived2 classes.



Here are my questions related to above scenario:

How about size of a Derived3 class object, Does it mean Derived3 class has 2 vptr?

How does the Derived3 class work with these 2 vptr, Any ideas about the mechanism it uses?

The sizeof classes is left as implementation detail of compiler & not defined by the Standard(as the virtual mechanism itself is an implementation detail of compilers)?










share|improve this question




















  • 1





    regarding the Standard question. Yes the mechanism of how to implement virtual methods is an implementation details and not specified. Yes the actual result of sizeof is an implementation details too, it notably depends on pointer size, if you were on a 64 bits platform, you would be seeing 8/8/8/16.

    – Matthieu M.
    Mar 31 '11 at 18:12
















4















I understand that the Diamond shaped inheritance causes ambiguity and it can be avoided by using inheritance through virtual Base Classes, the question is not about it. The question is about sizeof the most derived class in a diamond shaped hierarchy when the classes are polymorphic. Here is a sample code and the sample output:



#include<iostream>

using namespace std;

class Base
{
public:
virtual void doSomething(){}
};

class Derived1:public virtual Base
{
public:
virtual void doSomething(){}
};

class Derived2:public virtual Base
{
public:
virtual void doSomething(){}
};

class Derived3:public Derived1,public Derived2
{
public:
virtual void doSomething(){}
};

int main()
{
Base obj;
Derived1 objDerived1;
Derived2 objDerived2;
Derived3 objDerived3;

cout<<"n Size of Base: "<<sizeof(obj);
cout<<"n Size of Derived1: "<<sizeof(objDerived1);
cout<<"n Size of Derived2: "<<sizeof(objDerived2);
cout<<"n Size of Derived3: "<<sizeof(objDerived3);

return 0;
}


The output i get is:



 Size of Base: 4
Size of Derived1: 4
Size of Derived2: 4
Size of Derived3: 8


As I understand Base contains a virtual member function and hence,

sizeof Base = size of vptr = 4 on this environment



Similar is the case Derived1 & Derived2 classes.



Here are my questions related to above scenario:

How about size of a Derived3 class object, Does it mean Derived3 class has 2 vptr?

How does the Derived3 class work with these 2 vptr, Any ideas about the mechanism it uses?

The sizeof classes is left as implementation detail of compiler & not defined by the Standard(as the virtual mechanism itself is an implementation detail of compilers)?










share|improve this question




















  • 1





    regarding the Standard question. Yes the mechanism of how to implement virtual methods is an implementation details and not specified. Yes the actual result of sizeof is an implementation details too, it notably depends on pointer size, if you were on a 64 bits platform, you would be seeing 8/8/8/16.

    – Matthieu M.
    Mar 31 '11 at 18:12














4












4








4


2






I understand that the Diamond shaped inheritance causes ambiguity and it can be avoided by using inheritance through virtual Base Classes, the question is not about it. The question is about sizeof the most derived class in a diamond shaped hierarchy when the classes are polymorphic. Here is a sample code and the sample output:



#include<iostream>

using namespace std;

class Base
{
public:
virtual void doSomething(){}
};

class Derived1:public virtual Base
{
public:
virtual void doSomething(){}
};

class Derived2:public virtual Base
{
public:
virtual void doSomething(){}
};

class Derived3:public Derived1,public Derived2
{
public:
virtual void doSomething(){}
};

int main()
{
Base obj;
Derived1 objDerived1;
Derived2 objDerived2;
Derived3 objDerived3;

cout<<"n Size of Base: "<<sizeof(obj);
cout<<"n Size of Derived1: "<<sizeof(objDerived1);
cout<<"n Size of Derived2: "<<sizeof(objDerived2);
cout<<"n Size of Derived3: "<<sizeof(objDerived3);

return 0;
}


The output i get is:



 Size of Base: 4
Size of Derived1: 4
Size of Derived2: 4
Size of Derived3: 8


As I understand Base contains a virtual member function and hence,

sizeof Base = size of vptr = 4 on this environment



Similar is the case Derived1 & Derived2 classes.



Here are my questions related to above scenario:

How about size of a Derived3 class object, Does it mean Derived3 class has 2 vptr?

How does the Derived3 class work with these 2 vptr, Any ideas about the mechanism it uses?

The sizeof classes is left as implementation detail of compiler & not defined by the Standard(as the virtual mechanism itself is an implementation detail of compilers)?










share|improve this question
















I understand that the Diamond shaped inheritance causes ambiguity and it can be avoided by using inheritance through virtual Base Classes, the question is not about it. The question is about sizeof the most derived class in a diamond shaped hierarchy when the classes are polymorphic. Here is a sample code and the sample output:



#include<iostream>

using namespace std;

class Base
{
public:
virtual void doSomething(){}
};

class Derived1:public virtual Base
{
public:
virtual void doSomething(){}
};

class Derived2:public virtual Base
{
public:
virtual void doSomething(){}
};

class Derived3:public Derived1,public Derived2
{
public:
virtual void doSomething(){}
};

int main()
{
Base obj;
Derived1 objDerived1;
Derived2 objDerived2;
Derived3 objDerived3;

cout<<"n Size of Base: "<<sizeof(obj);
cout<<"n Size of Derived1: "<<sizeof(objDerived1);
cout<<"n Size of Derived2: "<<sizeof(objDerived2);
cout<<"n Size of Derived3: "<<sizeof(objDerived3);

return 0;
}


The output i get is:



 Size of Base: 4
Size of Derived1: 4
Size of Derived2: 4
Size of Derived3: 8


As I understand Base contains a virtual member function and hence,

sizeof Base = size of vptr = 4 on this environment



Similar is the case Derived1 & Derived2 classes.



Here are my questions related to above scenario:

How about size of a Derived3 class object, Does it mean Derived3 class has 2 vptr?

How does the Derived3 class work with these 2 vptr, Any ideas about the mechanism it uses?

The sizeof classes is left as implementation detail of compiler & not defined by the Standard(as the virtual mechanism itself is an implementation detail of compilers)?







c++ sizeof virtual-inheritance diamond-problem memory-layout






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 7 '15 at 21:38









curiousguy

4,51222943




4,51222943










asked Mar 31 '11 at 16:17









Alok SaveAlok Save

164k35340482




164k35340482








  • 1





    regarding the Standard question. Yes the mechanism of how to implement virtual methods is an implementation details and not specified. Yes the actual result of sizeof is an implementation details too, it notably depends on pointer size, if you were on a 64 bits platform, you would be seeing 8/8/8/16.

    – Matthieu M.
    Mar 31 '11 at 18:12














  • 1





    regarding the Standard question. Yes the mechanism of how to implement virtual methods is an implementation details and not specified. Yes the actual result of sizeof is an implementation details too, it notably depends on pointer size, if you were on a 64 bits platform, you would be seeing 8/8/8/16.

    – Matthieu M.
    Mar 31 '11 at 18:12








1




1





regarding the Standard question. Yes the mechanism of how to implement virtual methods is an implementation details and not specified. Yes the actual result of sizeof is an implementation details too, it notably depends on pointer size, if you were on a 64 bits platform, you would be seeing 8/8/8/16.

– Matthieu M.
Mar 31 '11 at 18:12





regarding the Standard question. Yes the mechanism of how to implement virtual methods is an implementation details and not specified. Yes the actual result of sizeof is an implementation details too, it notably depends on pointer size, if you were on a 64 bits platform, you would be seeing 8/8/8/16.

– Matthieu M.
Mar 31 '11 at 18:12












4 Answers
4






active

oldest

votes


















4














Yes, Derived3 has two vtable pointers. If you're accessing it by value, it uses the Derived3 version, or picks a function from a parent, or denotes that it's ambiguous if it can't decide.



In the case of a child, it uses the vtable corresponding to the parent 1/2 that's being used polymorphically.



Note that you didn't use virtual inheritance correctly: I believe Derived1 and 2 should inherit virtually from Base. sizeof(Derived3) still seems to be 8, because it still has two possible parents that could be treated as a Derived3. When you cast up to one of the parents the compiler will actually adjust the object pointer to have the correct vtable.



Also I should point out that anything vtable-related is implementation specific because there isn't even any mention of vtables in the standard.






share|improve this answer
























  • Thanks, I corrected the typo of the Derived1 & Derived2 virtually inheriting from Base. The O/P is still the same.

    – Alok Save
    Mar 31 '11 at 16:32



















3














A small fix to your code: the virtual is supposed to be in the definition of derived2 and derived 3 in order to work.



http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.9






share|improve this answer
























  • Thanks I corrected the typo

    – Alok Save
    Mar 31 '11 at 16:39



















1














I think you are wondering about something that is totally implementation specific.
You should not assume anything about the size of the classes.



Edit: though being curious is a proven quality ;-)






share|improve this answer































    1














    Consider a slightly different case:



    struct B { virtual void f(); };
    struct L : virtual B { virtual void g(); };
    struct R : virtual B { virtual void h(); };
    struct D : L, R {};


    In a typical implementation, L::g will be in the same position (say at
    index 0) in L's vtable as R:h in R's vtable. Now consider what happens
    given the following code:



    D* pd = new D;
    L* pl = pd;
    R* pr = pd;
    pl->g();
    pr->h();


    In the last two lines, the compiler will generate code to find the
    address of the function at the same position in the vtable. So the
    vtable accessed through pl cannot be the same as the one (or a prefix of
    the one) accessed through pr. Thus, the complete object needs at least
    two vptr, to point to two different vtable.






    share|improve this answer
























    • actually in typical implementation f would probably come before g or h in the virtual table, so that no adjustement is necessary when using L or R polymorphically as a B (that is the layout of the L table will be a superset of the layout of the B table, so that the B view of it conforms to B attempts).

      – Matthieu M.
      Mar 31 '11 at 18:11






    • 1





      @Matthieu M. Yes. In a lot of implementations, the vtable will start with one or more special pointers, to type_info information, for example, followed by the virtual functions in the base classes, in order, then the virtual functions of the class which aren't overrides of a base. The fact remains, however, that the vtable for L will have g in the same place as the vtable for R has h, so the same vtable cannot be used for both L and R in D.

      – James Kanze
      Apr 1 '11 at 7:51











    • exact, in a lot of implementations. Building smarter vtables require whole program analysis / link-time optimization.

      – Matthieu M.
      Apr 1 '11 at 12:23











    • Thats a interesting/convincing explanation.Thanks!

      – Alok Save
      Apr 4 '11 at 6:07











    • @MatthieuM. "the layout of the L table will be a superset" The invariants of the L table will be...

      – curiousguy
      Nov 19 '18 at 21:19











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5502994%2fdiamond-shaped-polymorphic-inheritance-sizeof-most-derived-class%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    4














    Yes, Derived3 has two vtable pointers. If you're accessing it by value, it uses the Derived3 version, or picks a function from a parent, or denotes that it's ambiguous if it can't decide.



    In the case of a child, it uses the vtable corresponding to the parent 1/2 that's being used polymorphically.



    Note that you didn't use virtual inheritance correctly: I believe Derived1 and 2 should inherit virtually from Base. sizeof(Derived3) still seems to be 8, because it still has two possible parents that could be treated as a Derived3. When you cast up to one of the parents the compiler will actually adjust the object pointer to have the correct vtable.



    Also I should point out that anything vtable-related is implementation specific because there isn't even any mention of vtables in the standard.






    share|improve this answer
























    • Thanks, I corrected the typo of the Derived1 & Derived2 virtually inheriting from Base. The O/P is still the same.

      – Alok Save
      Mar 31 '11 at 16:32
















    4














    Yes, Derived3 has two vtable pointers. If you're accessing it by value, it uses the Derived3 version, or picks a function from a parent, or denotes that it's ambiguous if it can't decide.



    In the case of a child, it uses the vtable corresponding to the parent 1/2 that's being used polymorphically.



    Note that you didn't use virtual inheritance correctly: I believe Derived1 and 2 should inherit virtually from Base. sizeof(Derived3) still seems to be 8, because it still has two possible parents that could be treated as a Derived3. When you cast up to one of the parents the compiler will actually adjust the object pointer to have the correct vtable.



    Also I should point out that anything vtable-related is implementation specific because there isn't even any mention of vtables in the standard.






    share|improve this answer
























    • Thanks, I corrected the typo of the Derived1 & Derived2 virtually inheriting from Base. The O/P is still the same.

      – Alok Save
      Mar 31 '11 at 16:32














    4












    4








    4







    Yes, Derived3 has two vtable pointers. If you're accessing it by value, it uses the Derived3 version, or picks a function from a parent, or denotes that it's ambiguous if it can't decide.



    In the case of a child, it uses the vtable corresponding to the parent 1/2 that's being used polymorphically.



    Note that you didn't use virtual inheritance correctly: I believe Derived1 and 2 should inherit virtually from Base. sizeof(Derived3) still seems to be 8, because it still has two possible parents that could be treated as a Derived3. When you cast up to one of the parents the compiler will actually adjust the object pointer to have the correct vtable.



    Also I should point out that anything vtable-related is implementation specific because there isn't even any mention of vtables in the standard.






    share|improve this answer













    Yes, Derived3 has two vtable pointers. If you're accessing it by value, it uses the Derived3 version, or picks a function from a parent, or denotes that it's ambiguous if it can't decide.



    In the case of a child, it uses the vtable corresponding to the parent 1/2 that's being used polymorphically.



    Note that you didn't use virtual inheritance correctly: I believe Derived1 and 2 should inherit virtually from Base. sizeof(Derived3) still seems to be 8, because it still has two possible parents that could be treated as a Derived3. When you cast up to one of the parents the compiler will actually adjust the object pointer to have the correct vtable.



    Also I should point out that anything vtable-related is implementation specific because there isn't even any mention of vtables in the standard.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Mar 31 '11 at 16:23









    Mark BMark B

    85.2k583164




    85.2k583164













    • Thanks, I corrected the typo of the Derived1 & Derived2 virtually inheriting from Base. The O/P is still the same.

      – Alok Save
      Mar 31 '11 at 16:32



















    • Thanks, I corrected the typo of the Derived1 & Derived2 virtually inheriting from Base. The O/P is still the same.

      – Alok Save
      Mar 31 '11 at 16:32

















    Thanks, I corrected the typo of the Derived1 & Derived2 virtually inheriting from Base. The O/P is still the same.

    – Alok Save
    Mar 31 '11 at 16:32





    Thanks, I corrected the typo of the Derived1 & Derived2 virtually inheriting from Base. The O/P is still the same.

    – Alok Save
    Mar 31 '11 at 16:32













    3














    A small fix to your code: the virtual is supposed to be in the definition of derived2 and derived 3 in order to work.



    http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.9






    share|improve this answer
























    • Thanks I corrected the typo

      – Alok Save
      Mar 31 '11 at 16:39
















    3














    A small fix to your code: the virtual is supposed to be in the definition of derived2 and derived 3 in order to work.



    http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.9






    share|improve this answer
























    • Thanks I corrected the typo

      – Alok Save
      Mar 31 '11 at 16:39














    3












    3








    3







    A small fix to your code: the virtual is supposed to be in the definition of derived2 and derived 3 in order to work.



    http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.9






    share|improve this answer













    A small fix to your code: the virtual is supposed to be in the definition of derived2 and derived 3 in order to work.



    http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.9







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Mar 31 '11 at 16:24









    ManicQinManicQin

    11418




    11418













    • Thanks I corrected the typo

      – Alok Save
      Mar 31 '11 at 16:39



















    • Thanks I corrected the typo

      – Alok Save
      Mar 31 '11 at 16:39

















    Thanks I corrected the typo

    – Alok Save
    Mar 31 '11 at 16:39





    Thanks I corrected the typo

    – Alok Save
    Mar 31 '11 at 16:39











    1














    I think you are wondering about something that is totally implementation specific.
    You should not assume anything about the size of the classes.



    Edit: though being curious is a proven quality ;-)






    share|improve this answer




























      1














      I think you are wondering about something that is totally implementation specific.
      You should not assume anything about the size of the classes.



      Edit: though being curious is a proven quality ;-)






      share|improve this answer


























        1












        1








        1







        I think you are wondering about something that is totally implementation specific.
        You should not assume anything about the size of the classes.



        Edit: though being curious is a proven quality ;-)






        share|improve this answer













        I think you are wondering about something that is totally implementation specific.
        You should not assume anything about the size of the classes.



        Edit: though being curious is a proven quality ;-)







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 31 '11 at 16:23









        Stephane RollandStephane Rolland

        19.1k2698146




        19.1k2698146























            1














            Consider a slightly different case:



            struct B { virtual void f(); };
            struct L : virtual B { virtual void g(); };
            struct R : virtual B { virtual void h(); };
            struct D : L, R {};


            In a typical implementation, L::g will be in the same position (say at
            index 0) in L's vtable as R:h in R's vtable. Now consider what happens
            given the following code:



            D* pd = new D;
            L* pl = pd;
            R* pr = pd;
            pl->g();
            pr->h();


            In the last two lines, the compiler will generate code to find the
            address of the function at the same position in the vtable. So the
            vtable accessed through pl cannot be the same as the one (or a prefix of
            the one) accessed through pr. Thus, the complete object needs at least
            two vptr, to point to two different vtable.






            share|improve this answer
























            • actually in typical implementation f would probably come before g or h in the virtual table, so that no adjustement is necessary when using L or R polymorphically as a B (that is the layout of the L table will be a superset of the layout of the B table, so that the B view of it conforms to B attempts).

              – Matthieu M.
              Mar 31 '11 at 18:11






            • 1





              @Matthieu M. Yes. In a lot of implementations, the vtable will start with one or more special pointers, to type_info information, for example, followed by the virtual functions in the base classes, in order, then the virtual functions of the class which aren't overrides of a base. The fact remains, however, that the vtable for L will have g in the same place as the vtable for R has h, so the same vtable cannot be used for both L and R in D.

              – James Kanze
              Apr 1 '11 at 7:51











            • exact, in a lot of implementations. Building smarter vtables require whole program analysis / link-time optimization.

              – Matthieu M.
              Apr 1 '11 at 12:23











            • Thats a interesting/convincing explanation.Thanks!

              – Alok Save
              Apr 4 '11 at 6:07











            • @MatthieuM. "the layout of the L table will be a superset" The invariants of the L table will be...

              – curiousguy
              Nov 19 '18 at 21:19
















            1














            Consider a slightly different case:



            struct B { virtual void f(); };
            struct L : virtual B { virtual void g(); };
            struct R : virtual B { virtual void h(); };
            struct D : L, R {};


            In a typical implementation, L::g will be in the same position (say at
            index 0) in L's vtable as R:h in R's vtable. Now consider what happens
            given the following code:



            D* pd = new D;
            L* pl = pd;
            R* pr = pd;
            pl->g();
            pr->h();


            In the last two lines, the compiler will generate code to find the
            address of the function at the same position in the vtable. So the
            vtable accessed through pl cannot be the same as the one (or a prefix of
            the one) accessed through pr. Thus, the complete object needs at least
            two vptr, to point to two different vtable.






            share|improve this answer
























            • actually in typical implementation f would probably come before g or h in the virtual table, so that no adjustement is necessary when using L or R polymorphically as a B (that is the layout of the L table will be a superset of the layout of the B table, so that the B view of it conforms to B attempts).

              – Matthieu M.
              Mar 31 '11 at 18:11






            • 1





              @Matthieu M. Yes. In a lot of implementations, the vtable will start with one or more special pointers, to type_info information, for example, followed by the virtual functions in the base classes, in order, then the virtual functions of the class which aren't overrides of a base. The fact remains, however, that the vtable for L will have g in the same place as the vtable for R has h, so the same vtable cannot be used for both L and R in D.

              – James Kanze
              Apr 1 '11 at 7:51











            • exact, in a lot of implementations. Building smarter vtables require whole program analysis / link-time optimization.

              – Matthieu M.
              Apr 1 '11 at 12:23











            • Thats a interesting/convincing explanation.Thanks!

              – Alok Save
              Apr 4 '11 at 6:07











            • @MatthieuM. "the layout of the L table will be a superset" The invariants of the L table will be...

              – curiousguy
              Nov 19 '18 at 21:19














            1












            1








            1







            Consider a slightly different case:



            struct B { virtual void f(); };
            struct L : virtual B { virtual void g(); };
            struct R : virtual B { virtual void h(); };
            struct D : L, R {};


            In a typical implementation, L::g will be in the same position (say at
            index 0) in L's vtable as R:h in R's vtable. Now consider what happens
            given the following code:



            D* pd = new D;
            L* pl = pd;
            R* pr = pd;
            pl->g();
            pr->h();


            In the last two lines, the compiler will generate code to find the
            address of the function at the same position in the vtable. So the
            vtable accessed through pl cannot be the same as the one (or a prefix of
            the one) accessed through pr. Thus, the complete object needs at least
            two vptr, to point to two different vtable.






            share|improve this answer













            Consider a slightly different case:



            struct B { virtual void f(); };
            struct L : virtual B { virtual void g(); };
            struct R : virtual B { virtual void h(); };
            struct D : L, R {};


            In a typical implementation, L::g will be in the same position (say at
            index 0) in L's vtable as R:h in R's vtable. Now consider what happens
            given the following code:



            D* pd = new D;
            L* pl = pd;
            R* pr = pd;
            pl->g();
            pr->h();


            In the last two lines, the compiler will generate code to find the
            address of the function at the same position in the vtable. So the
            vtable accessed through pl cannot be the same as the one (or a prefix of
            the one) accessed through pr. Thus, the complete object needs at least
            two vptr, to point to two different vtable.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Mar 31 '11 at 17:09









            James KanzeJames Kanze

            129k9137278




            129k9137278













            • actually in typical implementation f would probably come before g or h in the virtual table, so that no adjustement is necessary when using L or R polymorphically as a B (that is the layout of the L table will be a superset of the layout of the B table, so that the B view of it conforms to B attempts).

              – Matthieu M.
              Mar 31 '11 at 18:11






            • 1





              @Matthieu M. Yes. In a lot of implementations, the vtable will start with one or more special pointers, to type_info information, for example, followed by the virtual functions in the base classes, in order, then the virtual functions of the class which aren't overrides of a base. The fact remains, however, that the vtable for L will have g in the same place as the vtable for R has h, so the same vtable cannot be used for both L and R in D.

              – James Kanze
              Apr 1 '11 at 7:51











            • exact, in a lot of implementations. Building smarter vtables require whole program analysis / link-time optimization.

              – Matthieu M.
              Apr 1 '11 at 12:23











            • Thats a interesting/convincing explanation.Thanks!

              – Alok Save
              Apr 4 '11 at 6:07











            • @MatthieuM. "the layout of the L table will be a superset" The invariants of the L table will be...

              – curiousguy
              Nov 19 '18 at 21:19



















            • actually in typical implementation f would probably come before g or h in the virtual table, so that no adjustement is necessary when using L or R polymorphically as a B (that is the layout of the L table will be a superset of the layout of the B table, so that the B view of it conforms to B attempts).

              – Matthieu M.
              Mar 31 '11 at 18:11






            • 1





              @Matthieu M. Yes. In a lot of implementations, the vtable will start with one or more special pointers, to type_info information, for example, followed by the virtual functions in the base classes, in order, then the virtual functions of the class which aren't overrides of a base. The fact remains, however, that the vtable for L will have g in the same place as the vtable for R has h, so the same vtable cannot be used for both L and R in D.

              – James Kanze
              Apr 1 '11 at 7:51











            • exact, in a lot of implementations. Building smarter vtables require whole program analysis / link-time optimization.

              – Matthieu M.
              Apr 1 '11 at 12:23











            • Thats a interesting/convincing explanation.Thanks!

              – Alok Save
              Apr 4 '11 at 6:07











            • @MatthieuM. "the layout of the L table will be a superset" The invariants of the L table will be...

              – curiousguy
              Nov 19 '18 at 21:19

















            actually in typical implementation f would probably come before g or h in the virtual table, so that no adjustement is necessary when using L or R polymorphically as a B (that is the layout of the L table will be a superset of the layout of the B table, so that the B view of it conforms to B attempts).

            – Matthieu M.
            Mar 31 '11 at 18:11





            actually in typical implementation f would probably come before g or h in the virtual table, so that no adjustement is necessary when using L or R polymorphically as a B (that is the layout of the L table will be a superset of the layout of the B table, so that the B view of it conforms to B attempts).

            – Matthieu M.
            Mar 31 '11 at 18:11




            1




            1





            @Matthieu M. Yes. In a lot of implementations, the vtable will start with one or more special pointers, to type_info information, for example, followed by the virtual functions in the base classes, in order, then the virtual functions of the class which aren't overrides of a base. The fact remains, however, that the vtable for L will have g in the same place as the vtable for R has h, so the same vtable cannot be used for both L and R in D.

            – James Kanze
            Apr 1 '11 at 7:51





            @Matthieu M. Yes. In a lot of implementations, the vtable will start with one or more special pointers, to type_info information, for example, followed by the virtual functions in the base classes, in order, then the virtual functions of the class which aren't overrides of a base. The fact remains, however, that the vtable for L will have g in the same place as the vtable for R has h, so the same vtable cannot be used for both L and R in D.

            – James Kanze
            Apr 1 '11 at 7:51













            exact, in a lot of implementations. Building smarter vtables require whole program analysis / link-time optimization.

            – Matthieu M.
            Apr 1 '11 at 12:23





            exact, in a lot of implementations. Building smarter vtables require whole program analysis / link-time optimization.

            – Matthieu M.
            Apr 1 '11 at 12:23













            Thats a interesting/convincing explanation.Thanks!

            – Alok Save
            Apr 4 '11 at 6:07





            Thats a interesting/convincing explanation.Thanks!

            – Alok Save
            Apr 4 '11 at 6:07













            @MatthieuM. "the layout of the L table will be a superset" The invariants of the L table will be...

            – curiousguy
            Nov 19 '18 at 21:19





            @MatthieuM. "the layout of the L table will be a superset" The invariants of the L table will be...

            – curiousguy
            Nov 19 '18 at 21:19


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5502994%2fdiamond-shaped-polymorphic-inheritance-sizeof-most-derived-class%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Tangent Lines Diagram Along Smooth Curve

            Yusuf al-Mu'taman ibn Hud

            Zucchini