vtable always needed

Discussion in 'C++' started by stef, Apr 16, 2007.

  1. stef

    stef Guest

    Hello,

    Could you tell me why did a C++ compiler really need to use a v-table
    in this case :


    #include <iostream>
    using namespace std;

    struct A {
    virtual void f() { cout << "Class A" << endl; }
    };

    struct B: A {
    virtual void f() { cout << "Class B" << endl; }
    };



    int main()
    {
    B x;
    A *ptr;

    ptr = &x;

    // could be "compute" statically ?
    ptr->f();

    return 1;
    }


    thanks...
    stef, Apr 16, 2007
    #1
    1. Advertising

  2. stef

    mlimber Guest

    On Apr 16, 11:34 am, "stef" <> wrote:
    > Hello,
    >
    > Could you tell me why did a C++ compiler really need to use a v-table
    > in this case :
    >
    > #include <iostream>
    > using namespace std;
    >
    > struct A {
    > virtual void f() { cout << "Class A" << endl; }
    >
    > };
    >
    > struct B: A {
    > virtual void f() { cout << "Class B" << endl; }
    >
    > };
    >
    > int main()
    > {
    > B x;
    > A *ptr;
    >
    > ptr = &x;
    >
    > // could be "compute" statically ?
    > ptr->f();
    >
    > return 1;
    >
    > }
    >
    > thanks...


    I could conceive of an optimizer getting rid of such a virtual
    function call, but since obvious optimizations like this are rare in
    real code, I wouldn't be surprised if the optimizer didn't bother.

    Cheers! --M
    mlimber, Apr 16, 2007
    #2
    1. Advertising

  3. stef wrote:

    > Could you tell me
    > why did a C++ compiler really need to use a v-table in this case:


    > cat fred.cc

    #include <iostream>
    using namespace std;

    struct A {
    virtual void f(void) {
    std::cout << "Class A" << std::endl; }
    };

    struct B: A {
    virtual void f(void) {
    std::cout << "Class B" << std::endl; }
    };

    void fred(void) {
    B x;
    A *ptr;

    ptr = &x;

    // could be "compute" statically?
    ptr->f();

    return;
    }

    > g++ -Wall -ansi -O2 -S fred.cc

    fred.cc:4: warning: ‘struct A’ has virtual functions
    but non-virtual destructor
    fred.cc:9: warning: ‘struct B’ has virtual functions
    but non-virtual destructor
    > cat fred.s

    .
    .
    .
    _Z4fredv:
    .LFB1435:
    pushl %ebp
    .LCFI0:
    movl %esp, %ebp
    .LCFI1:
    subl $24, %esp
    .LCFI2:
    leal -4(%ebp), %eax
    movl $_ZTV1B+8, -4(%ebp)
    movl %eax, (%esp)
    call *_ZTV1B+8
    leave
    ret
    .
    .
    .
    _ZTV1B:
    .long 0
    .long _ZTI1B
    .long _ZN1B1fEv
    .weak _ZTI1B
    .section .rodata._ZTI1B,"aG",@progbits,_ZTI1B,comdat
    .align 4
    .type _ZTI1B, @object
    .size _ZTI1B, 12
    .
    .
    .
    > c++filt _ZTV1B

    vtable for B
    > c++filt _ZN1B1fEv

    B::f()
    > g++ --version

    g++ (GCC) 4.1.1 20070105 (Red Hat 4.1.1-51)

    My optimizing C++ compiler actually calls B::f() directly.

    ----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
    http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
    ----= East and West-Coast Server Farms - Total Privacy via Encryption =----
    E. Robert Tisdale, Apr 16, 2007
    #3
  4. stef

    Salt_Peter Guest

    On Apr 16, 11:34 am, "stef" <> wrote:
    > Hello,
    >
    > Could you tell me why did a C++ compiler really need to use a v-table
    > in this case :
    >
    > #include <iostream>
    > using namespace std;
    >
    > struct A {
    > virtual void f() { cout << "Class A" << endl; }
    >
    > };
    >
    > struct B: A {
    > virtual void f() { cout << "Class B" << endl; }
    >
    > };
    >
    > int main()
    > {
    > B x;
    > A *ptr;
    >
    > ptr = &x;
    >
    > // could be "compute" statically ?
    > ptr->f();
    >
    > return 1;
    >
    > }
    >
    > thanks...


    What if you added:

    struct C: B {
    };

    int main()
    {
    C x;
    A *ptr;

    ptr = &x;

    ptr->f(); // what should the compiler do here?
    }
    Salt_Peter, Apr 16, 2007
    #4
  5. stef

    Markus Moll Guest

    Hi

    Salt_Peter wrote:
    > What if you added:
    >
    > struct C: B {
    > };
    >
    > int main()
    > {
    > C x;
    > A *ptr;
    >
    > ptr = &x;
    >
    > ptr->f(); // what should the compiler do here?
    > }


    Of course it should still call B::f(), and that could be easily
    determined at compile-time, without the need for any runtime dispatch.

    Markus
    Markus Moll, Apr 17, 2007
    #5
  6. stef

    Markus Moll Guest

    Hi

    E. Robert Tisdale wrote:
    > .LCFI2:
    > leal -4(%ebp), %eax
    > movl $_ZTV1B+8, -4(%ebp)
    > movl %eax, (%esp)
    > call *_ZTV1B+8
    > leave
    > ret
    > .
    > .
    > .
    > _ZTV1B:
    > .long 0
    > .long _ZTI1B
    > .long _ZN1B1fEv
    > .weak _ZTI1B
    > .section .rodata._ZTI1B,"aG",@progbits,_ZTI1B,comdat
    > .align 4
    > .type _ZTI1B, @object
    > .size _ZTI1B, 12

    [...]
    > My optimizing C++ compiler actually calls B::f() directly.


    Well, I would only call "call _ZN1B1fEv" a direct call to B::f().
    But that's strange. The compiler is smart enough to know that it's
    dealing with a "B" and eliminates the indirection through the pointer to
    the virtual table, but still it cannot infer that it should therefore
    simply call B::f()?

    Could it be that this is because gcc does not want to break code where
    people intentionally mess around with virtual tables while the program
    is running?

    Markus
    Markus Moll, Apr 17, 2007
    #6
  7. Markus Moll wrote:
    > Hi
    >
    > E. Robert Tisdale wrote:
    >> .LCFI2:
    >> leal -4(%ebp), %eax
    >> movl $_ZTV1B+8, -4(%ebp)
    >> movl %eax, (%esp)
    >> call *_ZTV1B+8
    >> leave
    >> ret
    >> .
    >> .
    >> .
    >> _ZTV1B:
    >> .long 0
    >> .long _ZTI1B
    >> .long _ZN1B1fEv
    >> .weak _ZTI1B
    >> .section .rodata._ZTI1B,"aG",@progbits,_ZTI1B,comdat
    >> .align 4
    >> .type _ZTI1B, @object
    >> .size _ZTI1B, 12

    > [...]
    >> My optimizing C++ compiler actually calls B::f() directly.

    >
    > Well, I would only call "call _ZN1B1fEv" a direct call to B::f().
    > But that's strange. The compiler is smart enough to know that it's
    > dealing with a "B" and eliminates the indirection through the pointer to
    > the virtual table, but still it cannot infer that it should therefore
    > simply call B::f()?
    >
    > Could it be that this is because gcc does not want to break code where
    > people intentionally mess around with virtual tables while the program
    > is running?


    I don't know.
    I'd guess that the optimizer is still "suboptimal".

    ----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
    http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
    ----= East and West-Coast Server Farms - Total Privacy via Encryption =----
    E. Robert Tisdale, Apr 17, 2007
    #7
    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. Deryck
    Replies:
    4
    Views:
    517
    derek giroulle
    Jun 22, 2004
  2. Pani
    Replies:
    2
    Views:
    360
    Alexander Terekhov
    Jul 23, 2003
  3. Daniel Heiserer
    Replies:
    1
    Views:
    2,909
    Artie Gold
    Aug 1, 2003
  4. r
    Replies:
    2
    Views:
    700
    Rob Williscroft
    Aug 2, 2003
  5. sks_cpp

    type_info, vtable

    sks_cpp, Aug 19, 2003, in forum: C++
    Replies:
    54
    Views:
    2,244
    Ron Natalie
    Aug 27, 2003
Loading...

Share This Page