C++ programming Pointers to members and basic guidelines for using this Pointers

  • 2020-05-07 20:13:33
  • OfStack

pointer to a member
's declaration of Pointers to members is a special case of pointer declarations. Declare them using the following sequence:


[storage-class-specifiers] [cv-qualifiers] type-specifiers [ms-modifier]
qualified-name ::* [cv-qualifiers] identifier
[= & qualified-name :: member-name];

Declaration specifier:

Optional storage class specifier. Optional const and/or volatile specifiers. Type specifier: the name of the type. This is the type of the member to point to, not the class.

The declarator:

Optional Microsoft special modifier. The qualified name of the class that contains the member to point to. :: operator. * operator. Optional const and/or volatile specifiers. An identifier that names a pointer to a member.

Optional initializer:

= operator. The & operator. The qualified name of the class. :: operator. The name of a nonstatic member of a class of the appropriate type.

As usual 1, multiple declarators (and any associated initializers) are allowed in a single declaration.
A pointer to a member of a class is different from a normal pointer in that it has type information for the member's type and type information for the class to which the member belongs. A regular pointer identifies only one object in memory or has only its address. A pointer to a member of a class identifies that member in all instances of the class. The following examples declare classes, Window, and some Pointers to member data.


// pointers_to_members1.cpp
class Window
{
public:
 Window();        // Default constructor.
 Window( int x1, int y1,     // Constructor specifying
 int x2, int y2 );      // window size.
bool SetCaption( const char *szTitle ); // Set window caption.
 const char *GetCaption();    // Get window caption.
 char *szWinCaption;      // Window caption.
};

// Declare a pointer to the data member szWinCaption.
char * Window::* pwCaption = &Window::szWinCaption;
int main()
{
}

In the previous example, pwCaption was a pointer to any member of a class of type Windowchar*. Type pwCaption is not char * Window::*. The next code snippet declares Pointers as SetCaption and GetCaption member functions.


const char * (Window::*pfnwGC)() = &Window::GetCaption;
bool (Window::*pfnwSC)( const char * ) = &Window::SetCaption;

The Pointers pfnwGC and pfnwSC point to SetCaption and Window of the GetCaption class, respectively. The following code directly copies the information to the window title using the pointer to member pwCaption:


Window wMainWindow;
Window *pwChildWindow = new Window;
char *szUntitled = "Untitled - ";
int cUntitledLen = strlen( szUntitled );

strcpy_s( wMainWindow.*pwCaption, cUntitledLen, szUntitled );
(wMainWindow.*pwCaption)[cUntitledLen - 1] = '1';  //same as
//wMainWindow.SzWinCaption [cUntitledLen - 1] = '1';
strcpy_s( pwChildWindow->*pwCaption, cUntitledLen, szUntitled ); 
(pwChildWindow->*pwCaption)[cUntitledLen - 1] = '2'; //same as //pwChildWindow->szWinCaption[cUntitledLen - 1] = '2';

. * and � > The * operator (pointer operator to a member) differs in that the.* operator selects the object or object reference given to the member, while the > The * operator selects members through Pointers. (for more information about these operators, see expressions that use pointer operators to members.)
The result of the pointer operator to a member is the type of member - char * in this case.
The following code snippet calls the member functions GetCaption and SetCaption with Pointers to members:


// Allocate a buffer.
enum {
 sizeOfBuffer = 100
};
char szCaptionBase[sizeOfBuffer];

// Copy the main window caption into the buffer
// and append " [View 1]".
strcpy_s( szCaptionBase, sizeOfBuffer, (wMainWindow.*pfnwGC)() );
strcat_s( szCaptionBase, sizeOfBuffer, " [View 1]" );
// Set the child window's caption.
(pwChildWindow->*pfnwSC)( szCaptionBase );

limits Pointers to members
The address of the
static member is not a pointer to the member. It is a regular pointer to an instance of a static member. Since only one static member instance exists for all objects of a given class, you can use the normal address-of (&) and dereference (*) operators.
points to Pointers to members and virtual functions
calls virtual functions with Pointers to member functions as if it were calling function 1 directly. The correct function is looked up and called in the v table.
Since then, the key to virtual functions is to call them with Pointers to base classes. (for more information about virtual functions, see virtual functions.)
The following code demonstrates how to call a virtual function with a pointer to a member function:


// virtual_functions.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

class Base
{
public:
virtual void Print();
};
void (Base ::* bfnPrint)() = &Base :: Print;
void Base :: Print()
{
cout << "Print function for class Base\n";
}

class Derived : public Base
{
public:
void Print(); // Print is still a virtual function.
};

void Derived :: Print()
{
cout << "Print function for class Derived\n";
}

int main()
{
 Base *bPtr;
 Base bObject;
Derived dObject;
bPtr = &bObject; // Set pointer to address of bObject.
(bPtr->*bfnPrint)();
bPtr = &dObject; // Set pointer to address of dObject.
(bPtr->*bfnPrint)();
}

//Output: Print function for class Base
Print function for class Derived

this pointer
The
this pointer is a pointer that can only be accessed in a non-static member function of type class, struct, or union. It points to the object for which the member function is called. Static member functions do not have an this pointer.
grammar


  this 
this->member-identifier

note
The this pointer to the object is not part 1 of the object; It is not reflected in the result of the sizeof statement on the object. Instead, when a non-static member function is called on an object, the object's address is passed to the function as a hidden argument by the compiler. For example, the following function calls:


myDate.setMonth( 3 );

It can be explained in the following way:


setMonth( &myDate, 3 );

The address of the object can be provided from within the member function as an this pointer. Most use of this is implicit. It is legal, but not necessary, to explicitly use this when referencing a member of a class. Such as:


void Date::setMonth( int mn )
{
 month = mn;   // These three statements
 this->month = mn;  // are equivalent
 (*this).month = mn;
}

Expression *this is commonly used to return the current object from a member function:


// pointers_to_members1.cpp
class Window
{
public:
 Window();        // Default constructor.
 Window( int x1, int y1,     // Constructor specifying
 int x2, int y2 );      // window size.
bool SetCaption( const char *szTitle ); // Set window caption.
 const char *GetCaption();    // Get window caption.
 char *szWinCaption;      // Window caption.
};

// Declare a pointer to the data member szWinCaption.
char * Window::* pwCaption = &Window::szWinCaption;
int main()
{
}

0

The this pointer is also used to prevent self-referencing:


// pointers_to_members1.cpp
class Window
{
public:
 Window();        // Default constructor.
 Window( int x1, int y1,     // Constructor specifying
 int x2, int y2 );      // window size.
bool SetCaption( const char *szTitle ); // Set window caption.
 const char *GetCaption();    // Get window caption.
 char *szWinCaption;      // Window caption.
};

// Declare a pointer to the data member szWinCaption.
char * Window::* pwCaption = &Window::szWinCaption;
int main()
{
}

1

Pay attention to
Since the this pointer cannot be changed, assignments to this are not allowed. Early implementations of C++ allowed for assignment to this.
The this pointer can sometimes be used directly - for example, when manipulating a self-referential data structure where the address of the current object is required.


// pointers_to_members1.cpp
class Window
{
public:
 Window();        // Default constructor.
 Window( int x1, int y1,     // Constructor specifying
 int x2, int y2 );      // window size.
bool SetCaption( const char *szTitle ); // Set window caption.
 const char *GetCaption();    // Get window caption.
 char *szWinCaption;      // Window caption.
};

// Declare a pointer to the data member szWinCaption.
char * Window::* pwCaption = &Window::szWinCaption;
int main()
{
}

2

Output:


my buffer
your buffer

Type of this pointer
modifies the type of volatilethis pointer in the function declaration with const and the keyword. To declare a function as a feature with one or more keywords, add the keyword to the end of the function argument list.
See the following example:


// pointers_to_members1.cpp
class Window
{
public:
 Window();        // Default constructor.
 Window( int x1, int y1,     // Constructor specifying
 int x2, int y2 );      // window size.
bool SetCaption( const char *szTitle ); // Set window caption.
 const char *GetCaption();    // Get window caption.
 char *szWinCaption;      // Window caption.
};

// Declare a pointer to the data member szWinCaption.
char * Window::* pwCaption = &Window::szWinCaption;
int main()
{
}

4

The code above declares a member function X, where the this pointer is considered to be an const pointer to the const object. You can use a combination of the cv-mod-list options, but they always modify the object pointed to through this, not the this pointer itself. Therefore, the following declaration declares the function X; The this pointer is the const pointer to the const object:


// pointers_to_members1.cpp
class Window
{
public:
 Window();        // Default constructor.
 Window( int x1, int y1,     // Constructor specifying
 int x2, int y2 );      // window size.
bool SetCaption( const char *szTitle ); // Set window caption.
 const char *GetCaption();    // Get window caption.
 char *szWinCaption;      // Window caption.
};

// Declare a pointer to the data member szWinCaption.
char * Window::* pwCaption = &Window::szWinCaption;
int main()
{
}

5

The type of the this pointer in the member function is described by the following syntax, where cv-qualifier-list is determined from the member function declaration and can be const and/or volatile, while class-type is the name of the class:


// pointers_to_members1.cpp
class Window
{
public:
 Window();        // Default constructor.
 Window( int x1, int y1,     // Constructor specifying
 int x2, int y2 );      // window size.
bool SetCaption( const char *szTitle ); // Set window caption.
 const char *GetCaption();    // Get window caption.
 char *szWinCaption;      // Window caption.
};

// Declare a pointer to the data member szWinCaption.
char * Window::* pwCaption = &Window::szWinCaption;
int main()
{
}

6

In other words, this is always an const pointer; It cannot be reassigned. The const or volatile qualifier used in the member function declaration applies to the class instance pointed to by this in the function scope.
The following table provides more information about how these modifiers work.
The semantics of the this modifier

修饰符
含义
const 不能更改数据成员;无法调用不是 const 的成员函数。
volatile 每次访问成员数据时,都会从内存中加载该数据;禁用某些优化。

It is an error to pass an const object to a member function that is not const. Similarly, it is an error to pass an volatile object to a member function that is not volatile.
A member function declared as const cannot change the data member - in this class, the this pointer is a pointer to the const object.
Pay attention to
Constructors and destructors cannot be declared as const or volatile. However, you can call them on const or volatile objects.


Related articles: