Doubt regarding Virtual Inheritance

Discussion in 'C++' started by Anarki, Jul 6, 2007.

  1. Anarki

    Anarki Guest

    ##include <iostream>
    using namespace std;

    class A
    {
    };
    class B:virtual public A
    {
    };
    class C:virtual public A
    {
    };
    class D:public B, public C
    {
    };

    int main()
    {

    cout << "Sizeof(A) " << sizeof(A) << endl;
    cout << "Sizeof(B) " << sizeof(B) << endl;
    cout << "Sizeof(C) " << sizeof(C) << endl;
    cout << "Sizeof(D) " << sizeof(D) << endl;
    return 0;
    }
    usually virtual inheritance comes into action to resolve the ambiguty
    of data access of grandparent class when there exist more than 1 path
    between grandparent and grandchild.

    Ok i take it as granted VI resolves data access ambiguity.

    But please take look at the output of the program i gave

    1
    4 //Any virtual pointer to a virtual function table? Note i havent
    specified and virtual functions
    4 //Any virtual pointer to a virtual function table? Note i havent
    specified and virtual functions
    8 //Two vptrs of B and C??

    if there are vptrs what is their role in avoiding the data access
    ambiguity?

    i will also give another analysis of memory structure with and without
    virtual inheritance.
    Anarki, Jul 6, 2007
    #1
    1. Advertising

  2. Anarki

    Anarki Guest

    ok this is an upgraded prog of the above one

    #include <iostream>
    using namespace std;

    class A
    {
    public:
    int a;
    A():a(10){}
    };
    class B:public A
    {
    public:
    int b;
    B():b(20){}
    };
    class C:public A
    {
    public:
    int c;
    C():c(30){}
    };
    class D:public B, public C
    {
    public:
    int d;
    D():d(40){}
    };

    int main()
    {
    int size[4];

    size[0] = sizeof(A);
    size[1] = sizeof(B);
    size[2] = sizeof(C);
    size[3] = sizeof(D);

    cout << "Sizeof(A) " << size[0] << endl;
    cout << "Sizeof(B) " << size[1] << endl;
    cout << "Sizeof(C) " << size[2] << endl;
    cout << "Sizeof(D) " << size[3] << endl << endl;

    /*
    * The following operations are done for
    * the sake for anatomy of structure of
    * memory alignment in an object.
    */

    int i = 0;
    int count = 0;
    int *p = NULL;
    cout << "Analysis of object of A" << endl;
    A a;
    p = (int*)&a;
    for(i = 0, count = 0; i < size[0]; i += 4, ++count)
    cout << "*(pa + " << count << ") = " << *(p + count) << endl;
    cout << endl;

    cout << "Analysis of object of B" << endl;
    B b;
    p = (int*)&b;
    for(i = 0, count = 0; i < size[1]; i += 4, ++count)
    cout << "*(p + " << count << ") = " << *(p + count) << endl;
    cout << endl;

    cout << "Analysis of object of C" << endl;
    C c;
    p = (int*)&c;
    for(i = 0, count = 0; i < size[2]; i += 4, ++count)
    cout << "*(p + " << count << ") = " << *(p + count) << endl;
    cout << endl;

    cout << "Analysis of object of D" << endl;
    D d;
    p = (int*)&d;
    for(i = 0, count = 0; i < size[3]; i += 4, ++count)
    cout << "*(p + " << count << ") = " << *(p + count) << endl;
    cout << endl;

    return 0;
    }

    if you people got time check the program with and without virtual
    keyword. You can see virtual pointers are there in action. whats their
    role in virtual inheritance even though i didnt declare any virtual
    functions?.

    I even checked the virtual address table its empty (since no virtual
    function). Whats is purpose of a virtual table/pointer in virtual
    inheritance even though there is no virtual function?

    moderators please pardon for making a huge post...
    Anarki, Jul 6, 2007
    #2
    1. Advertising

  3. On 2007-07-06 12:25, Anarki wrote:
    > ok this is an upgraded prog of the above one
    >
    > #include <iostream>
    > using namespace std;
    >
    > class A
    > {
    > public:
    > int a;
    > A():a(10){}
    > };
    > class B:public A
    > {
    > public:
    > int b;
    > B():b(20){}
    > };
    > class C:public A
    > {
    > public:
    > int c;
    > C():c(30){}
    > };
    > class D:public B, public C
    > {
    > public:
    > int d;
    > D():d(40){}
    > };
    >
    > int main()
    > {
    > int size[4];
    >
    > size[0] = sizeof(A);
    > size[1] = sizeof(B);
    > size[2] = sizeof(C);
    > size[3] = sizeof(D);
    >
    > cout << "Sizeof(A) " << size[0] << endl;
    > cout << "Sizeof(B) " << size[1] << endl;
    > cout << "Sizeof(C) " << size[2] << endl;
    > cout << "Sizeof(D) " << size[3] << endl << endl;
    >
    > /*
    > * The following operations are done for
    > * the sake for anatomy of structure of
    > * memory alignment in an object.
    > */
    >
    > int i = 0;
    > int count = 0;
    > int *p = NULL;
    > cout << "Analysis of object of A" << endl;
    > A a;
    > p = (int*)&a;
    > for(i = 0, count = 0; i < size[0]; i += 4, ++count)
    > cout << "*(pa + " << count << ") = " << *(p + count) << endl;
    > cout << endl;
    >
    > cout << "Analysis of object of B" << endl;
    > B b;
    > p = (int*)&b;
    > for(i = 0, count = 0; i < size[1]; i += 4, ++count)
    > cout << "*(p + " << count << ") = " << *(p + count) << endl;
    > cout << endl;
    >
    > cout << "Analysis of object of C" << endl;
    > C c;
    > p = (int*)&c;
    > for(i = 0, count = 0; i < size[2]; i += 4, ++count)
    > cout << "*(p + " << count << ") = " << *(p + count) << endl;
    > cout << endl;
    >
    > cout << "Analysis of object of D" << endl;
    > D d;
    > p = (int*)&d;
    > for(i = 0, count = 0; i < size[3]; i += 4, ++count)
    > cout << "*(p + " << count << ") = " << *(p + count) << endl;
    > cout << endl;
    >
    > return 0;
    > }
    >
    > if you people got time check the program with and without virtual
    > keyword. You can see virtual pointers are there in action. whats their
    > role in virtual inheritance even though i didnt declare any virtual
    > functions?.
    >
    > I even checked the virtual address table its empty (since no virtual
    > function). Whats is purpose of a virtual table/pointer in virtual
    > inheritance even though there is no virtual function?


    Compiler vendors are free to implement the standard as they choose,
    trying to infer things about the language from an implementation is
    doomed to fail. The reason you see this behaviour (whatever it is) is
    probably because your vendor thought that this implementation was the
    best way to implement things.

    > moderators please pardon for making a huge post...


    This is an unmoderated group, and the post is not very large compared to
    some others.

    --
    Erik Wikström
    =?ISO-8859-1?Q?Erik_Wikstr=F6m?=, Jul 6, 2007
    #3
  4. Anarki

    Pete Becker Guest

    Anarki wrote:
    >
    > Ok i take it as granted VI resolves data access ambiguity.
    >


    Virtual inheritance is an implementation technique. Data access
    ambiguity is either a design error or a coding error. If it's the result
    of a design error, changing to a single base class (using virtual
    inheritance) may be the right solution. But it should never be an
    automatic reaction to ambiguity.

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
    Pete Becker, Jul 6, 2007
    #4
  5. Anarki

    gpuchtel Guest

    On Jul 6, 6:25 am, Anarki <> wrote:

    > Whats is purpose of a virtual table/pointer in virtual
    > inheritance even though there is no virtual function?


    I'm not a compiler writer, nor am I a guru; however I did read Stanley
    Lippman's book: "Inside the C++ Object Module". To paraphrase, he
    describes the presence of a virtual table (in this case) as a general
    implementation solution to support a form of shared subobject
    inheritance when a class has one or more virtual base classes. The
    virtual table is used to store the location of invariant and shared
    regions of the object. Therefore, its presence (in your case) is the
    result of having a virtual base class, not virtual functions.
    gpuchtel, Jul 6, 2007
    #5
  6. Anarki

    James Kanze Guest

    On Jul 6, 12:16 pm, Anarki <> wrote:
    > #include <iostream>
    > using namespace std;


    > class A
    > {};


    > class B:virtual public A
    > {};


    > class C:virtual public A
    > {};


    > class D:public B, public C
    > {
    > };


    > int main()
    > {
    > cout << "Sizeof(A) " << sizeof(A) << endl;
    > cout << "Sizeof(B) " << sizeof(B) << endl;
    > cout << "Sizeof(C) " << sizeof(C) << endl;
    > cout << "Sizeof(D) " << sizeof(D) << endl;
    > return 0;}


    > usually virtual inheritance comes into action to resolve the ambiguty
    > of data access of grandparent class when there exist more than 1 path
    > between grandparent and grandchild.


    > Ok i take it as granted VI resolves data access ambiguity.


    I don't seem much relationship between resolving ambiguity and
    virtual inheritance. Virtual inheritance affects the form of
    the inheritance lattice. Design determines which form you want.
    If the resulting form results in ambiguities, you use scope
    resolution operators to resolve them, possibly introducing
    additional intermediate classes. You do not change the
    inheritance lattice without modifying the overall design.

    > But please take look at the output of the program i gave


    > 1
    > 4 //Any virtual pointer to a virtual function table? Note i havent
    > specified and virtual functions
    > 4 //Any virtual pointer to a virtual function table? Note i havent
    > specified and virtual functions
    > 8 //Two vptrs of B and C??


    > if there are vptrs what is their role in avoiding the data access
    > ambiguity?


    I'm afraid I don't even understand the question. Most
    implementations today use a single vptr to a table with all RTTI
    information. What the vtbl actually contains will vary a lot
    from one implementation to the next, however.

    One effect that virtual inhertance does have is that it means
    that the compiler cannot staticly know where the base class is
    situated compared to the derived class, so the compiler must use
    dynamic RTTI to convert derived to base. Thus, in your example
    above, if the complete object has type B, in a typical
    implementation, the A subobject will immediately follow the B
    specific data in the object. In a complete object of type D,
    however, the A subobject of the B subobject will generally
    follow both the B and the C subobjects, as well as any data
    specific to D. Given a B*, the compiler doesn't know which case
    holds, so it will use RTTI to determine where the A subobject
    is, relative to the address it has. And in order to do this, it
    will probably need a vptr in the object.

    Note that such analysis is much simpler if you insert a
    ptruint_t in each object, initializing it with a different value
    each time. You can then dump the object as an array of
    ptruint_t (undefined behavior, but in practice, it will work),
    and see where each sub-object is situated. Also, cast a pointer
    to the object to each of the sub-object types, and output that
    (as a void*). Then create objects of all the types involved,
    and see how the layout of a B as most derived class is different
    from that of a B sub-object in a D.

    --
    James Kanze (Gabi Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jul 7, 2007
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. qazmlp
    Replies:
    19
    Views:
    777
    Daniel T.
    Feb 4, 2004
  2. cppsks
    Replies:
    0
    Views:
    806
    cppsks
    Oct 27, 2004
  3. darkstorm
    Replies:
    3
    Views:
    343
    Malte Starostik
    Mar 29, 2005
  4. Ashwin
    Replies:
    2
    Views:
    337
    Pierre Barbier de Reuille
    Aug 1, 2006
  5. Replies:
    1
    Views:
    454
    Alf P. Steinbach
    Mar 14, 2009
Loading...

Share This Page