Casting a pointer to virtual member function from derived class tobase class

Discussion in 'C++' started by Alex Shen, Oct 16, 2010.

  1. Alex Shen

    Alex Shen Guest

    Hi all, pls consider the following code,

    #include <iostream>

    struct base
    {
    virtual void f()
    {
    std::cout << "base::f\n";
    }
    };

    struct derived : base
    {
    virtual void f()
    {
    std::cout << "derived::f\n";
    }
    };

    int main()
    {
    typedef void (base::* base_ptr_type)();
    typedef void (derived::* derived_ptr_type)();

    derived_ptr_type pd(&derived::f);
    base_ptr_type pb(reinterpret_cast<base_ptr_type>(pd));

    derived d;
    (static_cast<base*>(&d)->*pb)(); // output "derived::f"
    }

    IIRC, MFC uses this technique in it's message mapping implmentation.
    It's not portable, right? Because of the use of reinterpret_cast whose
    result is undefined as the standard says.

    Alex
     
    Alex Shen, Oct 16, 2010
    #1
    1. Advertising

  2. Re: Casting a pointer to virtual member function from derived class to base class

    Alex Shen <> wrote:
    > typedef void (base::* base_ptr_type)();
    > typedef void (derived::* derived_ptr_type)();
    >
    > derived_ptr_type pd(&derived::f);
    > base_ptr_type pb(reinterpret_cast<base_ptr_type>(pd));


    I don't know what the standard says about that, but I would be very
    surprised if it's not huge Undefined Behavior (especially since a
    virtual member function pointer is more complex than a regular function
    pointer).

    Also, I don't understand the need. You can have a pointer to a virtual
    function of the base class, and then use it to call the function for an
    object, and the dynamic binding will work (in other words, if the object
    is really of a derived type and that derived type implements the virtual
    function, the derived version will be called). There's no need for such
    hazardous casting.
     
    Juha Nieminen, Oct 16, 2010
    #2
    1. Advertising

  3. Alex Shen

    Alex Shen Guest

    Re: Casting a pointer to virtual member function from derived classto base class

    ÓÚ 2010/10/16 16:22, Juha Nieminen дµÀ:
    > Alex Shen<> wrote:
    >> typedef void (base::* base_ptr_type)();
    >> typedef void (derived::* derived_ptr_type)();
    >>
    >> derived_ptr_type pd(&derived::f);
    >> base_ptr_type pb(reinterpret_cast<base_ptr_type>(pd));

    >
    > I don't know what the standard says about that, but I would be very
    > surprised if it's not huge Undefined Behavior (especially since a
    > virtual member function pointer is more complex than a regular function
    > pointer).
    >
    > Also, I don't understand the need. You can have a pointer to a virtual
    > function of the base class, and then use it to call the function for an
    > object, and the dynamic binding will work (in other words, if the object
    > is really of a derived type and that derived type implements the virtual
    > function, the derived version will be called). There's no need for such
    > hazardous casting.

    Assume that I need to call a virtual function from the base class
    according to a runtime condition. By storing all pointers to virtual
    functions in a container, I can avoid the if-else statement to
    dertermine which virtual function to be called in the base class. I
    agree with you that this horrible casting should be avoided and function
    object such as boost::function can be used to store member function
    pointers.I'm just curious about such code.

    Alex
     
    Alex Shen, Oct 23, 2010
    #3
  4. Re: Casting a pointer to virtual member function from derived class to base class

    Alex Shen <> wrote:
    > Assume that I need to call a virtual function from the base class
    > according to a runtime condition. By storing all pointers to virtual
    > functions in a container, I can avoid the if-else statement to
    > dertermine which virtual function to be called in the base class.


    I still don't understand what the problem is. If you want to store
    member function pointers into a container, then store them. As said,
    if such a member function is virtual, calling it through the pointer
    will work ok (ie. the possible dynamic binding will be taken into account
    when calling the function, even if you do it through a base class member
    function pointer). What is the problem you are having?
     
    Juha Nieminen, Oct 23, 2010
    #4
  5. Alex Shen

    James Kanze Guest

    Re: Casting a pointer to virtual member function from derived classto base class

    On Oct 16, 6:30 am, Alex Shen <> wrote:
    > Hi all, pls consider the following code,


    > #include <iostream>


    > struct base
    > {
    > virtual void f()
    > {
    > std::cout << "base::f\n";
    > }
    > };


    > struct derived : base
    > {
    > virtual void f()
    > {
    > std::cout << "derived::f\n";
    > }
    > };


    > int main()
    > {
    > typedef void (base::* base_ptr_type)();
    > typedef void (derived::* derived_ptr_type)();


    > derived_ptr_type pd(&derived::f);
    > base_ptr_type pb(reinterpret_cast<base_ptr_type>(pd));


    This shouldn't require (or use) a reinterpret_cast.
    A static_cast is sufficient.

    > derived d;
    > (static_cast<base*>(&d)->*pb)(); // output "derived::f"
    > }


    > IIRC, MFC uses this technique in it's message mapping
    > implmentation. It's not portable, right? Because of the use
    > of reinterpret_cast whose result is undefined as the standard
    > says.


    Correct. Use a static_cast, and everything should be OK. (And
    Microsoft isn't the first to use this technique.)

    --
    James Kanze
     
    James Kanze, Oct 25, 2010
    #5
  6. Alex Shen

    Alex Shen Guest

    Re: Casting a pointer to virtual member function from derived classto base class

    于 2010/10/25 18:29, James Kanze 写é“:
    > On Oct 16, 6:30 am, Alex Shen<> wrote:
    >> Hi all, pls consider the following code,

    >
    >> #include<iostream>

    >
    >> struct base
    >> {
    >> virtual void f()
    >> {
    >> std::cout<< "base::f\n";
    >> }
    >> };

    >
    >> struct derived : base
    >> {
    >> virtual void f()
    >> {
    >> std::cout<< "derived::f\n";
    >> }
    >> };

    >
    >> int main()
    >> {
    >> typedef void (base::* base_ptr_type)();
    >> typedef void (derived::* derived_ptr_type)();

    >
    >> derived_ptr_type pd(&derived::f);
    >> base_ptr_type pb(reinterpret_cast<base_ptr_type>(pd));

    >
    > This shouldn't require (or use) a reinterpret_cast.
    > A static_cast is sufficient.


    Now, I believe that this technique is valid because we can use
    static_cast instead of the horrible reinterpret_cast. I just found
    paragraph 5.2.9/9 in C++03 draft which specifies this kind of casting.

    Alex
     
    Alex Shen, Oct 30, 2010
    #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. Xiangliang Meng
    Replies:
    2
    Views:
    425
    Jack Klein
    Jun 21, 2004
  2. Fraser Ross
    Replies:
    4
    Views:
    1,094
    Fraser Ross
    Aug 14, 2004
  3. archimed7592
    Replies:
    4
    Views:
    786
    =?UTF-8?B?UGF3ZcWC?=
    May 30, 2007
  4. naveen
    Replies:
    2
    Views:
    384
    Roedy Green
    Aug 4, 2007
  5. somenath
    Replies:
    2
    Views:
    178
    somenath
    Aug 29, 2013
Loading...

Share This Page