简体   繁体   中英

What does .*, ->* and .-> mean in C++?

I have been recently learning how to use the std::mem_fn library facility. In C++ Primer 5th edition they give an example of a usage of std::mem_fn , in the following code snippet svec is a vector of string s:

auto f = mem_fn(&string::empty); // f takes a string or a string*

f(*svec.begin()); // ok: passes a string object; f uses .* to call empty

f(&svec[0]); // ok: passes a pointer to string; f uses .-> to call empty

Note: In the above code snippet there is no use of ->*

Although I understand the usage .* and ->* . I don't have clarity on it.

So, My question is what does .* , ->* , .-> do?

You have an object o and a pointer to its member m . The operator .* allows you to access the pointed member of your object:

o.*m

You have a pointer to an object p and a pointer to its member m . The operator ->* allows you to access the pointed member of the pointed object:

p->*m

I am afraid that the operator .-> doesn't exist.

The .* and ->* operators are called pointer to member access operators and like their name suggests they allow you to access an object's data or function member given an appropriate pointer to that class member.

struct foo
{
    int a;
    float b;
    void bar() { std::cout << "bar\n"; }
};

int main()
{
    int foo::* ptra = &foo::a;
    float foo::* ptrb = &foo::b;
    void (foo::* ptrbar)() = &foo::bar;

    foo f;
    foo * fptr = &f;

    f.*ptra = 5;
    f.*ptrb = 10.0f;
    (f.*ptrbar)();

    fptr->*ptra = 6;
    fptr->*ptrb = 11.0f;
    (fptr->*ptrbar)();

    return 0;
}

Operators .* and ->* call a member function (BTW there is no meaning for .-> in C++ - it's a syntax error).

These are binary operators. The left operand is an object (for .* ) or a pointer to an object (for ->* ), and the right operand is a pointer to a member (which can be a member field or a member function). The outcome of applying this operator is the ability to use a member field or a method.

Maybe these operators make sense from a historical point of view. Suppose you use a regular C pointer to a function:

typedef int (*CalcResult)(int x, int y, int z);
CalcResult my_calc_func = &CalcResult42;
...
int result = my_calc_func(11, 22, 33);

What if you decided to "rewrite" your program in an object-oriented way? Your calculation function would be a method in a class. To make a pointer to it, you need a new type, a pointer to member function:

typedef int (MyClass::*CalcResult)(int x, int y, int z);
CalcResult my_calc_func = &MyClass::CalcResult42;
...
MyClass my_object;
int result = (my_object.*my_calc_func)(11, 22, 33);

I always use this analogy when I try to remember the syntax of this .* operator - this helps because the regular pointer-to-function syntax is less convoluted and used more frequently.

Please note the parentheses:

int result = (my_object.*my_calc_func)(11, 22, 33);

They are almost always needed when using this .* operator, because its precedence is low. Even though my_object .* (my_calc_func(11, 22, 33)) is meaningless, the compiler would try to make sense of it if there were no parentheses.

The ->* operator works in essentially the same way. It would be used if the object on which to apply the method is given by a pointer:

typedef int (*MyClass::CalcResult)(int x, int y, int z);
CalcResult my_calc_func = &MyClass::CalcResult42;
...
MyClass my_object1, my_object2;
MyClass* my_object = flag ? &my_object1 : &my_object2;
int result = (my_object->*my_calc_func)(11, 22, 33);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM