C++编程指向成员的指针以及this指针的基本使用指南_C 语言

指向成员的指针
指向成员的指针的声明是指针声明的特例。使用以下序列来声明它们:

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

声明说明符:

  • 可选存储类说明符。
  • 可选 const 和/或 volatile 说明符。
  • 类型说明符:类型的名称。这是要指向的成员的类型,而不是类。

声明符:

  • 可选的 Microsoft 专用修饰符。
  • 包含要指向的成员的类的限定名。
  • :: 运算符。
  • * 运算符。
  • 可选 const 和/或 volatile 说明符。
  • 命名指向成员的指针的标识符。

可选的初始值设定项:

  • = 运算符。
  • & 运算符。
  • 类的限定名。
  • :: 运算符。
  • 适当类型的类的非静态成员的名称。

像往常一样,允许在单个声明中使用多个声明符(以及任何关联的初始值设定项)。
指向类的成员的指针与普通指针不同,因为它有该成员的类型的类型信息和该成员所属的类的类型信息。常规指针只标识内存中的一个对象或只具有其地址。指向类的某个成员的指针标识类的所有实例中的该成员。以下示例声明类、Window 和一些指向成员数据的指针。

// 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()
{
}

在前面的示例中,pwCaption 是一个指针,它指向具有 Windowchar* 类型的类 的任何成员。类型 pwCaption 不是 char * Window::*。下一个代码片段将指针声明为 SetCaption 和 GetCaption 成员函数。

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

指针 pfnwGC 和 pfnwSC 分别指向 GetCaption 类的 SetCaption 和 Window。以下代码直接使用指向成员 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';

.* 和 –>* 运算符(指向成员的指针运算符)的区别在于 .* 运算符选择成员给定的对象或对象引用,而 –>* 运算符通过指针选择成员。(有关这些运算符的更多信息,请参阅使用指向成员的指针运算符的表达式。)
指向成员的指针运算符的结果是成员的类型 - 本例中为 char *。
以下代码片段使用指向成员的指针调用成员函数 GetCaption 和 SetCaption:

// 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 );

针对指向成员的指针的限制
静态成员的地址不是指向成员的指针。它是指向静态成员的一个实例的常规指针。由于给定类的所有对象只存在一个静态成员实例,因此可以使用普通的 address-of (&) 和取消引用 (*) 运算符。
指向成员和虚函数的指针
通过指向成员函数的指针调用虚函数就如同直接调用函数一样;将在 v 表中查找并调用正确的函数。
一直以来,虚函数工作的关键是通过指向基类的指针来调用它们。(有关虚函数的详细信息,请参阅虚函数。)
以下代码演示如何通过指向成员函数的指针调用虚函数:

// 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 指针
this 指针是只能在 class、struct或 union 类型的非静态成员函数中访问的指针。它指向为其调用成员函数的对象。静态成员函数没有 this 指针。
语法

  this
this->member-identifier

备注
对象的 this 指针不是对象的一部分;它没有在对象上的 sizeof 语句的结果中反映。相反,当对某个对象调用非静态成员函数时,该对象的地址将由编译器作为隐藏的参数传递给函数。例如,以下函数调用:

myDate.setMonth( 3 );

可以按以下方式解释:

setMonth( &myDate, 3 );

对象的地址可从成员函数的内部作为 this 指针提供。 this 的大多数使用都是隐式的。在引用类的成员时显式使用 this 是合法的,但没有必要。例如:

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

表达式 *this 通常用于从成员函数返回当前对象:

return *this;

this 指针还用于防止自引用:

if (&Object != this) {
// do not execute in cases of self-reference

注意
由于 this 指针无法更改,因此不允许对 this 赋值。C++ 的早期实现允许对 this 赋值。
this 指针有时可直接使用 - 例如,当操作自引用数据结构,而其中需要当前对象的地址时。

// this_pointer.cpp
// compile with: /EHsc

#include <iostream>
#include <string.h>

using namespace std;

class Buf
{
public:
 Buf( char* szBuffer, size_t sizeOfBuffer );
 Buf& operator=( const Buf & );
 void Display() { cout << buffer << endl; }

private:
 char* buffer;
 size_t sizeOfBuffer;
};

Buf::Buf( char* szBuffer, size_t sizeOfBuffer )
{
 sizeOfBuffer++; // account for a NULL terminator

 buffer = new char[ sizeOfBuffer ];
 if (buffer)
 {
  strcpy_s( buffer, sizeOfBuffer, szBuffer );
  sizeOfBuffer = sizeOfBuffer;
 }
}

Buf& Buf::operator=( const Buf &otherbuf )
{
 if( &otherbuf != this )
 {
  if (buffer)
   delete [] buffer;

  sizeOfBuffer = strlen( otherbuf.buffer ) + 1;
  buffer = new char[sizeOfBuffer];
  strcpy_s( buffer, sizeOfBuffer, otherbuf.buffer );
 }
 return *this;
}

int main()
{
 Buf myBuf( "my buffer", 10 );
 Buf yourBuf( "your buffer", 12 );

 // Display 'my buffer'
 myBuf.Display();

 // assignment opperator
 myBuf = yourBuf;

 // Display 'your buffer'
 myBuf.Display();
}

输出:

my buffer
your buffer

this 指针的类型
通过 const 和 关键字,可以在函数声明中修改 volatilethis 指针的类型。若要将函数声明为具有一个或多个关键字的特性,请将关键字添加到函数参数列表的后面。
请看以下示例:

// type_of_this_pointer1.cpp
class Point
{
 unsigned X() const;
};
int main()
{
}

上面的代码声明一个成员函数 X,其中,this 指针被视为指向 const 对象的 const 指针。可以使用 cv-mod-list 选项的组合,但它们始终通过 this 修改指向的对象,而不是 this 指针本身。因此,以下声明将声明函数 X;this 指针是指向 const 对象的 const 指针:

// type_of_this_pointer2.cpp
class Point
{
 unsigned X() const;
};
int main()
{
}

成员函数中 this 指针的类型由以下语法描述,其中,cv-qualifier-list 是从成员函数声明符中确定的,可以是 const 和/或 volatile,而 class-type 是类的名称:

[cv-qualifier-list] class-type * const this

换言之,this 始终是 const 指针;无法重新指派它。成员函数声明中使用的 const 或 volatile 限定符适用于由该函数范围中的 this 指向的类实例。
下表介绍了有关这些修饰符的工作方式的更多信息。
this 修饰符的语义

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

将 const 对象传递给不是 const 的成员函数是错误的。同样,将 volatile 对象传递给不是 volatile 的成员函数也是错误的。
声明为 const 的成员函数不能更改数据成员 - 在此类函数中,this 指针是指向 const 对象的指针。
注意
构造函数和析构函数不能声明为 const 或 volatile。但是,可以在 const 或 volatile 对象上调用它们。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c++
, 指针
, this
成员
指南针的红色指针指向、指向成员函数的指针、指向类成员函数的指针、指南针白色指针指向、创建指向成员的指针,以便于您获取更多的相关知识。

时间: 2024-09-20 04:17:00

C++编程指向成员的指针以及this指针的基本使用指南_C 语言的相关文章

C++编程中将引用类型作为函数参数的方法指南_C 语言

有了变量名,为什么还需要一个别名呢?C++之所以增加引用类型, 主要是把它作为函数参数,以扩充函数传递数据的功能. 到目前为止我们介绍过函数参数传递的两种情况. 1) 将变量名作为实参和形参 这时传给形参的是变量的值,传递是单向的.如果在执行函数期间形参的值发生变化,并不传回给实参.因为在调用函数时,形参和实参不是同一个存储单元. [例]要求将变量i和j的值互换.下面的程序无法实现此要求. #include <iostream> using namespace std; int main( )

C++中指针的数据类型和运算相关知识小结_C 语言

C++有关指针的数据类型和指针运算的小结 前面已用过一些指针运算(如p++,p+i等),现在把全部的指针运算列出如下. 1) 指针变量加/减 一个整数 例如:p++,p--,p+i,p-i,p+-i,p-=i等. C++规定,一个指针变量加/减一个整数是将该指针变量的原值(是一个地址)和它指向的变量所占用的内存单元字节数相加或相减.如p+i代表这样的地址计算:p+i*d,d为p所指向的变量单元所占用的字节数.这样才能保证p+i指向p下面的第i个元素. 2) 指针变量赋值 将一个变量地址赋给一个指

c++ 指针与引用的区别介绍及使用说明_C 语言

指针与引用看上去完全不同(指针用操作符"*"和"->",引用使用操作符"."),但是它们似乎有相同的功能.指针与引用都是让你间接引用其他对象.你如何决定在什么时候使用指针,在什么时候使用引用呢? 首先,要认识到在任何情况下都不能使用指向空值的引用.一个引用必须总是指向某些对象.因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量.相反,如果变量肯定指向一

C/C++中指针和引用之相关问题深入研究_C 语言

一.基本知识指针和引用的声明方式:声明指针: char* pc;声明引用: char c = 'A'   char& rc = c; 它们的区别:①从现象上看,指针在运行时可以改变其所指向的值,而引用一旦和某个对象绑定后就不再改变.这句话可以理解为:指针可以被重新赋值以指向另一个不同的对象.但是引用则总是指向在初始化时被指定的对象,以后不能改变,但是指定的对象其内容可以改变. ②从内存分配上看,程序为指针变量分配内存区域,而不为引用分配内存区域,因为引用声明时必须初始化,从而指向一个已经存在的对

C++中的auto_ptr智能指针的作用及使用方法详解_C 语言

智能指针(auto_ptr) 这个名字听起来很酷是不是?其实auto_ptr 只是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势,但也有其局限.本文总结的8个问题足以涵盖auto_ptr的大部分内容.  auto_ptr是什么? auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者.当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥

C++编程中使用设计模式中的policy策略模式的实例讲解_C 语言

   在看<C++设计新思维>的时候,发现在一开始就大篇幅的介绍策略模式(policy),策略模式不属于经典设计模式中的一种,但是其实在我们日常的开发中是必不可少的.policy,策略,方针,这里的意思是指把复杂功能的类尽量的拆分为功能单一的简单类的组合,简单的类只负责单纯行为或结构的某一方面.增加程序库的弹性,可复用性,可扩展性.policy是一个虚拟的概念,他定义了某一类class的一些接口规范,并不与C++语法的关键字对应,只是一个抽象的概念. 实例1: //policy模式的常见使用实

C++编程异常处理中try和throw以及catch语句的用法_C 语言

若要在 C++ 中实现异常处理,你可以使用 try.throw 和 catch 表达式. 首先,使用 try 块将可能引发异常的一个或多个语句封闭起来. throw 表达式发出信号,异常条件(通常是错误)已在 try 块中发生.你可以使用任何类型的对象作为 throw 表达式的操作数.该对象一般用于传达有关错误的信息.大多数情况下,建议你使用 std::exception 类或标准库中定义的派生类之一.如果其中的类不合适,建议你从 std::exception 派生自己的异常类. 若要处理可能引

详解C++编程中的嵌套类的声明与其中的函数使用_C 语言

可以在一个类的范围内声明另一个类.这样的类称为"嵌套类". 嵌套类被视为在封闭类的范围内且可在该范围内使用.若要从嵌套类的即时封闭范围之外的某个范围引用该类,则必须使用完全限定名. 下面的示例演示如何声明嵌套类: // nested_class_declarations.cpp class BufferedIO { public: enum IOError { None, Access, General }; // Declare nested class BufferedInput.

C++编程中的或||、与&amp;&amp;、非!逻辑运算符基本用法整理_C 语言

逻辑或运算符:||  语法 logical-or-expression || logical-and-expression 备注 如果任一操作数或两个操作数为 true,则逻辑"或"运算符 (||) 返回布尔值 true:否则返回 false.操作数在计算之前隐式转换为类型 bool,结果的类型为 bool.逻辑"或"具有从左向右的关联性. 逻辑"或"运算符的操作数不需要是同一类型,但是它们必须是整型或指针类型.操作数通常为关系或相等表达式. 第