C ++ Summary of precautions related to "class" (5): pointer to class members

Source: Internet
Author: User

Assume that the screen class defines four new member functions: Forward () Back () Up () and down (). They move the cursor to the right, left, up, and down, respectively. First, we declare these new member functions in the class body:

Class Screen {
Public:
Inline screen & forward ();
Inline screen & back ();
Inline screen & End ();
Inline screen & up ();
Inline screen & down ();
// Other member functions are the same as those before
PRIVATE:
Inline int row ();
// Other private members are the same as the previous
};

 

A user of the screen class requires a function repeat (), which executes the operation specified by the user n times. Its non-general implementation is as follows:

Screen & repeat (char op, int times)
{
Switch (OP ){
Case down: // call screen: Down () n times
Break;
Case up: // call screen: Up () n times
Break;
//...
}
}

 

Although this implementation can work, it has many disadvantages. One problem is that it depends on the screen member function to remain unchanged. Each time a member function is added or removed, repeat () must be updated (); the second problem is its size. Because every possible member function must be tested, the complete list of repeat () is very large and not complex.
The alternative is a more general implementation. Replace op with the pointer type parameter of the screen member function. Repeat () does not need to determine what operations the user expects. The entire switch statement can also be removed.

 

I. Type of Class Members

 

The function pointer cannot be assigned the address of a member function, even if the return type exactly matches the parameter table. For example, the following PFI is a function pointer. This function has no parameters and the return type is int:

INT (* PFI )();

Two global functions heightis () and widthis () are provided ():

Int heightis ();
Int widthis ();

It is valid and correct to assign one or two values of heightis () and widthis () to the pointer PFI:

PFI = heightis;
PFI = widthis;

The Class Screen also defines two access functions -- height () and width () -- they also have no parameters, and the return type is also INT:

Inline int screen: height () {return _ height ;}
Inline int screen: width () {return _ width ;}

However, assigning any height () or width () to the pointer PFI is a type violation, which will cause compilation errors:


// Illegal Value assignment: type violation
PFI = & screen: height;

Why is there a type violation? A member function has an attribute that a non-member function does not have -- its class. The pointer to a member function must match the function type assigned to it, it must be matched in three aspects rather than two: (1) parameter type and number (2) return type (3) class type to which it belongs.

The member function pointer must be bound to an object or a pointer to obtain the this pointer of the called object before calling the member function referred to by the pointer. Although common function pointers and member function pointers are called pointers, they are different things.

The Declaration of the member function pointer requires the extended syntax. It should consider the type of the class, and the pointer to the class data member should also be like this. Consider the type of the screen class member height. Its complete type is "short-Type Screen class member", the complete type of pointer to _ height is the pointer to "a member of the Short-Type Screen class", which can be written:

Short screen ::*
 
The pointer to a member of the Short-Type Screen class is defined as follows:

 

Short screen: * ps_screen;
 
Ps_screen can be initialized with the _ height address, as shown below:

 
Short screen: * ps_screen = & screen: _ height;
 
Similarly, it can also assign values with the _ width address as follows:

Ps_screen = & screen: _ width;

 

To define a member function pointer, you must specify the function return type, parameter table, and Class. For example, the pointer type pointing to the screen member function and being able to reference the member function height () and width () is as follows:


INT (screen ::*)()

This type specifies a pointer to a member function of the screen class. It has no parameter and the return value type is int. The pointer to a member function can be declared, initialized, and assigned as follows:


// All pointers to class members can be assigned a value of 0.
INT (screen: * pmf1) () = 0;
INT (screen: * pmf2) () = & screen: height;
 
Pmf1 = pmf2;
Pmf2 = & screen: width;

Using typedef makes the syntax of member pointers easier to read. For example, the following type definition:


Screen & (screen ::*)()

That is, a pointer to the screen class member function. This function has no parameters and returns a reference to the screen class object. It can be replaced by the following typedef defined action:

 
Typedef screen & (screen: * Action )();
 
Action default = & screen: home;
Action next = & screen: forward;

Pointers to member function types can be used to declare function parameters and function return types. We can also specify default real parameters for Parameters of member function types. For example:

 

Screen & Action (screen &, action );

Action () is declared to have two parameters: a reference to a screen object and a pointer to a screen member function. This function has no parameters and returns a reference to a screen object. Action () can be called in any of the following ways:

 
Screen myscreen;
Typedef screen & (screen: * Action )();
Action default = & screen: home;
 
Extern screen & Action (screen &, Action = & screen: Display );
 
Void ff ()
{

Action (myscreen );
Action (myscreen, default );
Action (myscreen, & screen: End );
}

 

2. Use pointers to class members

 

The pointer of a class member must always be accessed through a specific object or pointer to an object of the class type. We use two pointers pointing to the member operator (for class objects and references. * And the pointer to the Class Object-> *). For example, we call the member function through the pointer of the member function as follows:


INT (screen: * pmfi) () = & screen: height;
Screen & (screen: * pmfs) (const screen &) = & screen: copy;
 
Screen myscreen, * bufscreen;
 
// Directly call the member function
If (myscreen. Height () = bufscreen-> height ())
Bufscreen-> copy (myscreen );
 
// Use the member pointer's equivalent call
If (myscreen. * pmfi) () = (bufscreen-> * pmfi )())
(Bufscreen-> * pmfs) (myscreen );

 

Call the following code:


(Myscreen. * pmfi )()
(Bufscreen-> * pmfi )()

Brackets are required because the call operator -- () -- has a higher priority than the Member operator pointer.

Myscreen. * pmfi ()
Will be interpreted
Myscreen. * (pmfi ())

It will first call the function pmfi () to bind its return value to the pointer of the member object operator. *. Of course, the pmfi type does not support this usage and will generate a compilation time error.

 

Pointers pointing to data members can be accessed in the following ways:

Typedef short screen: * ps_screen;
 
Screen myscreen, * tmpscreen = new screen (10, 10 );
 
Ps_screen pH = & screen: _ height;
Ps_screen PW = & screen: _ width;
 
Tmpscreen-> * pH = myscreen. * pH;
Tmpscreen-> * PW = myscreen. * PW;

 

The implementation of the member function repeat () discussed at the beginning is as follows. It is modified to use the pointer of a member function as the parameter:

 

Typedef screen & (screen: * Action )();
 
Screen & screen: Repeat (Action op, int time s)
{
For (INT I = 0; I <times; ++ I)
(This-> * op )();
 
Return * this;
}

 

The OP parameter is a member function pointer that points to the member function to be called times. To provide the default real parameter for the repeat () parameter, the Declaration is as follows:

 
Class Screen {
Public:
Screen & repeat (Action = & screen: Forward, Int = 1 );
//...
};

Repeat () is called as follows:

Screen myscreen;
Myscreen. Repeat (); // repeat (& screen: Forward, 1 );
Myscreen. Repeat (& screen: Down, 20 );

 

Iii. Static class member pointers

 

There is a difference between the pointers of non-static class members and the guidance of static class members. The pointer syntax pointing to class members cannot be used to reference static class members, static class members are global objects and functions of the class, and their pointers are normal pointers. (Remember that the static member function does not have the this pointer)


The pointer to a static class member seems to be the same as that of a non-class member. class objects are not required to reference the pointer. For example, let's take a look at the class account:

 

Class account {
Public:
Static void raiseinterest (double incr );
Static double interest () {return _ interestrate ;}
Double amount () {return _ amount ;}
PRIVATE:
Static double _ interestrate;
Double _ amount;
String _ owner;
};
 
Inline void account: raiseinterest (double incr)
{
_ Interestrate + = incr;
}

& _ The interestrate type is double * instead:
// Not the & _ interestrate type
Double account ::*

The pointer to _ interestrate is defined as follows:
// OK: Double * instead of double account ::*
Double * Pd = & account: _ interestrate;
It is dereferenced in the same way as a normal pointer and does not need related class objects, for example:
Account Unit;

// Use a common unreferenced Operator
Double daily = * Pd/365 * unit. _ amount;

 

However, because _ interestrate and _ amount are both private members, we need to use static member functions interest () and non-static member functions amount ().
The pointer to interest () is a normal function pointer.
// Correct
Double (*)()

Instead of the pointer to the member functions of the account class
// Incorrect
Double (account ::*)()

The definition of this pointer is the same as the indirect call processing method for interest () as that for non-class pointers:


// OK: douple (* PF) () is not double (account: * PF )()
Double (* PF) () = & account: interest;

Double daily = PF ()/365 * unit. Amount ();

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.