Member function pointer

what is the difference between double Box::*i and Box * I
Last edited on
The first one is almost pointer to a double, either in a class or a namespace. If it's in a class, it's likely to be some static variable when accessed like that. The syntax is a little off, though.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

struct Box
{
    static double* i;

};

double* Box::i = nullptr;

int main( int argc, char* argv[] )
{
    return 0;
}


The second just looks like a pointer to a Box class.

Neither of them are function pointers, though. And what you mean by 'member' function pointer is a little unclear in this context. It could be a member of a class that is a function pointer or a function pointer that points to a function of a class.

Function pointer member
1
2
3
4
struct Box
{
    void( *f_ptr )();
};


Function pointer to a class function
1
2
3
4
5
6
7
8
struct Box
{
   static int gimmeFive() { return 5; }
};

// Usage
int( *f_ptr )() = &Box::gimmeFive;
std::cout << f_ptr() << std::endl;
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <string>

struct Box
{
    double length ;
    double width ;
    double height ;

    std::string label ;

    static double sd ;

};

int main()
{
    // type of pmv is 'pointer to member variable of Box which is of type double'
    double Box::*pmv ;

    pmv = nullptr ; // it can be null
    pmv = &Box::length ; // or point to any non-static member of Box (of type double)
    pmv = &Box::width ;
    pmv = &Box::width ;

    // pmv = &Box::label ;// *** error: Box::lablel is not of type double

    // pmv = &Box::sd ; // *** error: Box::sd is not non-static
    double* pd = &Box::sd ; // fine, Box::sd is an ordinary double

    Box one, two ;
    Box* pb = &two ;

    // we can use a pointer to member this way:
    one.*pmv = 23.5 ; // set one's length to 23.5
    pb->*pmv = 50.4 ; // set two's length to 50.4
    pmv = &Box::height ;
    one.*pmv = 5.7 ; // set one's height to 5.7
}
JLBorges wrote:
1
2
// type of pmv is 'pointer to member variable of Box which is of type double'
    double Box::*pmv ;


Wow. I never actually knew you could do this.

So what are the advantages of this over a regular pointer to a double? These would be restricted to pointing to doubles only of that class? What if they didn't? Compile-time error?
> Wow. I never actually knew you could do this.

Especially after the advent of C++11, most programmers need never know about these esoteric beasts. Even in the very old days (pre-boost), the occasions to use them were rare. Now, with standard library provided polymorphic binder and polymorphic call wrapper, the usage of pointers to members in non-library C++ code had virtually disappeared.

> So what are the advantages of this over a regular pointer to a double?

The basic idea is straightforward. A pointer to an object can point to different objects of compatible types (or can be null). A pointer to member can point to different non-static members of compatible types (or can be null). Just a a pointer to object gives us the flexibility decide which object at run-time, a pointer to member gives us the flexibility decide which member at runtime. An example of this kind of usage (obsoleted by std::bind() and std::function<>) used to be in implementing flexible callbacks (say in an observer pattern).

Pointers to members are still useful for building abstractions (both std::bind() and std::function<> internally use pointers to member functions). For instance, in implementing the safe-bool idiom.
http://www.cplusplus.com/forum/general/104056/#msg561018


> These would be restricted to pointing to doubles only of that class?
> What if they didn't? Compile-time error?

Yes.

Though the object with which the pointer is dereferenced could be a derived class object. And if a pointer to a member function points to a virtual function in the base class, there are no surprises: it behaves polymorphically.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>

struct base
{
    double length ;
    double width ;
    double height ;

    virtual ~base() {}

    void not_polymorphic() const { std::cout << "base::not_polymorphic\n" ; }
    virtual void polymorphic() const { std::cout << "base::polymorphic\n" ; }
};

void foo( const base& b, void (base::*pmfn)() const ) { (b.*pmfn)() ; }

int main()
{
    struct derived : base
    {
        void not_polymorphic() const /* hide */
        { std::cout << "derived::not_polymorphic (hides base::not_polymorphic)\n" ; }

        virtual void polymorphic() const override
        { std::cout << "derived::polymorphic (overrides base::polymorphic)\n" ; }
    };

    base b ;
    derived d ;

    void (base::*pmfn)() const = &base::not_polymorphic ;
    foo( b, pmfn ) ; // base::not_polymorphic
    foo( d, pmfn ) ; // base::not_polymorphic

    pmfn = &base::polymorphic ;
    foo( b, pmfn ) ; // base::polymorphic
    foo( d, pmfn ) ; // derived::polymorphic (overrides base::polymorphic)

}

http://coliru.stacked-crooked.com/a/77678f51c6021eec
Excellent. Every day's a school day.

Cheers for the info.
Pointers to members are still useful for building abstractions

+1, I use them quite a bit in my daily work

Now the multi-level pointers to members I am yet to find a practical use for (see http://en.cppreference.com/w/cpp/language/pointer )
Thank you for everyone to reply for my doubt
Topic archived. No new replies allowed.