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

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

[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 对象上调用它们。

时间: 2016-01-19

详解C++中的this指针与常对象

C++ this指针详解 this 是C++中的一个关键字,也是一个常量指针,指向当前对象(具体说是当前对象的首地址).通过 this,可以访问当前对象的成员变量和成员函数. 所谓当前对象,就是正在使用的对象,例如对于stu.say();,stu 就是当前对象,系统正在访问 stu 的成员函数 say(). 假设 this 指向 stu 对象,那么下面的语句中,this 就和 pStu 的值相同: Student stu; //通过Student类来创建对象 Student *pStu = &s

C++中this指针的用法及介绍

this指针只能在一个类的成员函数中调用,它表示当前对象的地址.下面是一个例子:   复制代码 代码如下: void Date::setMonth( int mn )     {      month = mn; // 这三句是等价的      this->month = mn;      (*this).month = mn;     } 1. this只能在成员函数中使用.全局函数,静态函数都不能使用this.实际上,成员函数默认第一个参数为T* const register this.如:

C++基础之this指针与另一种“多态”

一.引入定义一个类的对象,首先系统已经给这个对象分配了空间,然后会调用构造函数. 一个类有多个对象,当程序中调用对象的某个函数时,有可能要访问到这个对象的成员变量.而对于同一个类的每一个对象,都是共享同一份类函数.对象有单独的变量,但是没有单独的函数,所以当调用函数时,系统必须让函数知道这是哪个对象的操作,从而确定成员变量是哪个对象的.这种用于对成员变量归属对像进行区分的东西,就叫做this指针.事实上它就是对象的地址,这一点从反汇编出来的代码可以看到. 二.分析1.测试代码: 复制代码 代码如

C++中this指针用法详解及实例

C++中this指针用法详解及实例 概要: 本文简单介绍this指针的基本概念,并通过一个实际例子介绍this指针用于防止变量命名冲突和用于类中层叠式调用的两个用法. this指针概览 C++中,每个类 对应了一个对象,每个对象指向自己所在内存地址的方式即为使用this指针.在类中,this指针作为一个变量通过编译器隐式传递给非暂存(non-static)成员函数.因为this指针不是对象本身,因此sizeof函数并不能用于确定this指针所对应的对象大小.this指针的具体类型与具体对象的类型

C/C++静态类和this指针详解及实例代码

 C/C++静态类和this指针详解 1.静态类 C++的静态成员不仅可以通过对象来访问,还可以直接通过类名来访问. class CBook{ public: static double price;//需要通过类外来进行初始化 } int main(void){ CBook book; book.price;//通过对象来访问 CBook::price//通过类名来访问 return 0; } 静态成员变量 对应静态成员有以下几点需要注意: (1)静态数据成员可以是当前类的类型,而其他数据成员

C++ 中的this指针详解及实例

C++ this 指针详解 学习 C++ 的指针既简单又有趣.通过指针,可以简化一些 C++ 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的.所以,想要成为一名优秀的 C++ 程序员,学习指针是很有必要的. 正如您所知道的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址. this指针是类的一个自动生成.自动隐蔽的私有成员,它存在于类的非静态成员中,指向被调用函数所在的对象. 全局仅有一个this指针,当一个对

深度理解c++中的this指针

1.this指针,就是一个指向当前对象的指针.我们知道,定义出一个类,它在内存中是不占空间的,只有定义了该类类型的对象时,系统就会为该对象分配一段存储空间,这段空间里只存储成员变量,对于成员函数,是存放在代码区的.(复习:内存分为5大区:静态区.常量区.栈.堆.代码区).下边给出一个日期类,通过这个实例,深度理解this指针. #define _CRT_SECURE_NO_WARNINGS 1 #include using namespace std; class Date { public:

理解java中的深复制和浅复制

Java语言的一个优点就是取消了指针的概念,但也导致了许多程序员在编程中常常忽略了对象与引用的区别,本文会试图澄清这一概念.并且由于Java不能通过简单的赋值来解决对象复制的问题,在开发过程中,也常常要要应用clone()方法来复制对象.本文会让你了解什么是影子clone与深度clone,认识它们的区别.优点及缺点. 看到这个标题,是不是有点困惑:Java语言明确说明取消了指针,因为指针往往是在带来方便的同时也是导致代码不安全的根源,同时也会使程序的变得非常复杂难以理解,滥用指针写成的代码不亚于

深入理解JavaScript中的对象复制(Object Clone)

JavaScript中并没有直接提供对象复制(Object Clone)的方法.因此下面的代码中改变对象b的时候,也就改变了对象a. a = {k1:1, k2:2, k3:3}; b = a; b.k2 = 4; 如果只想改变b而保持a不变,就需要对对象a进行复制. 用jQuery进行对象复制 在可以使用jQuery的情况下,jQuery自带的extend方法可以用来实现对象的复制. a = {k1:1, k2:2, k3:3}; b = {}; $.extend(b,a); 自定义clone

深入学习C语言中的函数指针和左右法则

通常的函数调用     一个通常的函数调用的例子: //自行包含头文件 void MyFun(int x); //此处的申明也可写成:void MyFun( int ); int main(int argc, char* argv[]) { MyFun(10); //这里是调用MyFun(10);函数 return 0; } void MyFun(int x) //这里定义一个MyFun函数 { printf("%d\n",x); } 这个MyFun函数是一个无返回值的函数,它并不完成

深入理解C#中的Delegate

在c#中,event与delegate是两个非常重要的概念.因为在Windows应用程序中,对事件的使用非常频繁,而事件的实现依赖于delegate. 下面是对网上一些比较好的关于delegage的资料的整理,以及自己的一些想法. Delegate是什么? Delegate中文翻译为"委托".Msdn中对Delegate的解释如下: C#中的委托类似于C或C++中的函数指针.使用委托使程序员可以将方法引用封装在委托对象内.然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时

深入理解Python中的*重复运算符

在python中有个特殊的符号"*",可以用做数值运算的乘法算子,也是用作对象的重复算子,但在作为重复算子使用时一定要注意 注意的是:*重复出来的各对象具有同一个id,也就是指向在内存中同一块地址,在对各个对象进行操作是一定要注意. 举例来说: >>> alist = [range(3)]*4 >>> alist [[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]] 上面初始化一个二层列表用来模拟矩阵,该矩阵式4X

AJAX入门之深入理解JavaScript中的函数

概述 函数是进行模块化程序设计的基础,编写复杂的Ajax应用程序,必须对函数有更深入的了解.JavaScript中的函数不同于其他的语言,每个函数都是作为一个对象被维护和运行的.通过函数对象的性质,可以很方便的将一个函数赋值给一个变量或者将函数作为参数传递.在继续讲述之前,先看一下函数的使用语法: function func1(-){-}var func2=function(-){-};var func3=function func4(-){-};var func5=new Function()

图文详解c/c++中的多级指针与多维数组

前言 首先先声明一些常识,如果你对这些常识还不理解,请先去弥补一下基础知识: 1.实际上并不存在多维数组,所谓的多维数组本质上是用一维数组模拟的. 2.数组名是一个常量(意味着不允许对其进行赋值操作),其代表数组首元素的首地址. 3.数组与指针的关系是因为数组下标操作符[],比如,int a[3][2]相当于*(*(a+3)+2) . 4.指针是一种变量,也具有类型,其占用内存空间大小和系统有关,一般32位系统下,sizeof(指针变量)=4. 5.指针可以进行加减算术运算,加减的基本单位是si

深入理解JavaScript中的call、apply、bind方法的区别

在JavaScript 中,this的指向是动态变化的,很可能在写程序的过程中,无意中破坏掉this的指向,所以我们需要一种可以把this的含义固定的技术,于是就有了call,apply 和bind这三个方法,来改变函数体内部 this 的指向,因为函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念 apply.call apply:应用某一对象的一个方法,用另一个对象替换当前对象 call:调用一个对象的一个方法,以另一个对象替换当前对象 function pers

详解C语言中的常量指针和指针常量

概述 对于新手来说,指针在c语言里总是一个非常难以理解的概念.在这篇文章中,我们将解释常量指针,指针常量,const pointer to const(ps:楼主以为这可以翻译成指向常量的常量指针)的区别 常量指针 让我们先来理解什么是常量指针.常量指针是指指针指向的地址是常量.换句话说,一旦常量指针指向了一个变量,你不能让该常量指针指向其他变量了 常量指针的声明方法如下: <type of pointer> * const <name of pointer> 常量指针声明示例: