Thread: Pointer-to-member functions

  1. #16
    Registered User
    Join Date
    Apr 2005
    Posts
    42
    Thank you very much for all of your help!

    Regards, Freddie.

  2. #17
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    I know C but am just teaching myself C++. The only way I got the code below
    to work was by following the original example (and replies) and chasing
    compiler error messages around as I permuted my brains out. It still seems
    like a potentially type-unsafe situation, however.

    In particular, this bit of the standard is a little worrying:
    "although class B need not contain the original member, the dynamic type of
    the object on which the pointer to member is dereferenced must contain the
    original member"

    I'm not sure what "dynamic type" means (I will look it up), but in the
    code below does B's "dynamic type" contain the original member function?
    If not, then since B seems to be "the object on which XXX is dereferenced",
    it does not seem to conform.

    At any rate, the code below works, but how would you connect the given template to it?
    Is it correct that the template's purpose is to obviate the static casting in D:()?
    (Hmm, I seem to have ended up with a big grin there. I was refering to D's constructor.)
    Code:
    template <typename T>
    void callT( void (T::*mem_fun)() ) {
        call(static_cast<fPtr>(mem_fun));
    }
    
    #include <iostream>
    using namespace std;
    
    class B {
      public:
        typedef bool (B::* fp_test_t) ();    /* Test func type; returns bool */
        typedef void (B::* fp_action_t) ();  /* Action func type             */
        B() { nfp = 0; }                     /* Zero function pointer count  */
        void add (fp_test_t, fp_action_t);
        void match();
      private:
        fp_test_t   fp_test[10];             /* Arrays used for simplicity   */
        fp_action_t fp_action[10];
        int nfp;                   /* Number of function pointers registered */
    };
    
    void B::add (fp_test_t test, fp_action_t act) {
        fp_test[ nfp ] = test;
        fp_action[ nfp ] = act;
        nfp++;
    }
    
    void B::match() {
        for (int i = 0; i < nfp; i++)
            if ((this->*fp_test[ i ])())
                (this->*fp_action[ i ])();
    }
    
    class D : public B {
      public:
        D();
        bool test1();
        void action1();
        bool test2();
        void action2();
    };
    
    D::D() {
        add( static_cast< B::fp_test_t   >( &D::test1 ),
             static_cast< B::fp_action_t >( &D::action1 ));
        add( static_cast< B::fp_test_t   >( &D::test2 ),
             static_cast< B::fp_action_t >( &D::action2 ));
    }
    bool D::test1()   { return false;    }
    void D::action1() { cout << "d1\n"; }
    bool D::test2()   { return true;    }
    void D::action2() { cout << "d2\n"; }
    
    int main() {
        D d;
        d.match();
    }
    Last edited by oogabooga; 01-11-2008 at 06:07 PM.

  3. #18
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by oogabooga View Post
    In particular, this bit of the standard is a little worrying:
    "although class B need not contain the original member, the dynamic type of
    the object on which the pointer to member is dereferenced must contain the
    original member"

    I'm not sure what "dynamic type" means (I will look it up), but in the
    code below does B's "dynamic type" contain the original member function?
    If not, then since B seems to be "the object on which XXX is dereferenced",
    it does not seem to conform.
    Well, as you know, not everything is always inherited from the base class. This is true if functions or member data is marked as private.
    If data or functions are marked as public or protected, they're inherited, thus class B which inherits from A would have all of A's member functions. But if those functions are private, B cannot inherit them.
    The problem stems that if you try to call a member function in A, the base class, and cast it to a pointer to call that function in the derived class, the function must exist! In other words, B must inherit the function from A, otherwise the result would be undefined.
    It's perfectly fine for B not to inherit a function in A, but if you cast that pointer and use it, the object (of type B) must inherit that function from A, the original function member.
    This, I believe, is what the standard says.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #19
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Correct me if I'm wrong, but are you saying (re-lettered to match the
    standard where B is base and D is derived):
    "If you call a member function in B through a pointer to D
    then D must have inherited that function (lest it not exist)."

    IF so, then you may be looking at it the wrong way round for this example.
    Here we are calling a member function of D through a pointer to B,
    not a member function of B through a pointer to D.

  5. #20
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Everything is always inherited. Private members are merely invisible, but they're still there.

    The dynamic type of an object is its actual type, whereas the static type is the type of the pointer/reference you're using to deal with it. E.g.:
    Code:
    B *b = new D;
    The static type is B, because b is a pointer to B, but the dynamic type is D.

    Given:
    Code:
    struct Base
    {
      int i1;
    };
    
    struct Derived : Base
    {
      int i2;
    };
    
    int Base::*pbasei;
    int Derived::*pderivedi;
    
    Base b;
    Derived d;
    Base &rb = d;
    1) "The null member pointer value is converted to the null member pointer value of the destination type." (5.2.9/9)
    Code:
    pderivedi = 0;
    pbasei = static_cast<int Base::*>(pderivedi);
    assert(pbasei == 0);
    2) "If class B contains the original member, [...] the resulting pointer to member points to the original member." (5.2.9/9)
    Code:
    pderivedi = &Derived::i1;
    pbasei = static_cast<int Base::*>(pderivedi);
    assert(pbasei == &Base::i1);
    b.*pbasei = 10; assert(b.i1 == 10);
    3) "If class B [...] is a base or derived class of the class containing the original member, the resulting pointer to member points to the original member." (5.2.9/9)
    Code:
    pderivedi = &Derived::i2;
    pbasei = static_cast<int Base::*>(pderivedi);
    rb.*pbasei = 10; assert(d.i2 == 10);
    4) "If the dynamic type of the object does not contain the member to which the pointer refers, the behavior is undefined." (5.5/4)
    Code:
    pderivedi = &Derived::i2;
    pbasei = static_cast<int Base::*>(pderivedi);
    b.*pbasei = 10; // UNDEFINED! b doesn't contain i2.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  6. #21
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by EvilGuru View Post
    Thank you very much for all of your help!

    Regards, Freddie.
    Please don't delete your post after your question has been answered. This makes it impossible for other people to search for and find the solution to their problem.

  7. #22
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The original member function of the inherited class must exist in the derived class, but the point is kind of moot since, as CornedBee mentions, the functions are always inherited, even if private.
    Therefore, it is always safe to do this, but might not be what you want.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 04-22-2008, 12:07 PM
  2. Replies: 2
    Last Post: 04-19-2008, 12:06 AM
  3. Ban pointers or references on classes?
    By Elysia in forum C++ Programming
    Replies: 89
    Last Post: 10-30-2007, 03:20 AM
  4. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  5. trouble defining member functions
    By dP munky in forum C++ Programming
    Replies: 7
    Last Post: 04-13-2003, 08:52 PM