1. 程式人生 > >指向類成員/函式的指標

指向類成員/函式的指標

C++擴充套件了指標在類中的使用,使其可以指向類成員,這種行為是類層面的,而不是物件層面的。

指向類成員/函式的指標的本質並不是取地址.而是利用了物件地址的偏移量

我們建立了一個類,假設我們要使用指標指向類中的成員

class Student {
public:
	Student(string n,int nu):name{n},num{nu}{}

	void  dis(int idx) {
		cout << idx << " " << name << " " << num << endl;
	}

public:
	string name;
	int num;
};

我們可以這麼做:string * ss1 = &s1.name;但是這樣做是沒有意義的,這樣會破壞類的封裝,這樣這個類就沒有存在意義了

C++提供了指向類成員的指標: 變數型別 類名::*pointer = &類名::變數名;

在這個類中,我們可以這麼使用

string Student::*pstr1 = &Student::name;

想要具體使用指標,我們還是要使用類的物件去呼叫,這是一種新的運算子,叫做指向類的指標

物件.*成員物件指標

指向物件指標->*成員物件指標

在本案例中可以這麼使用:

Student s1("zhangsan", 100);
Student* ps1 = &s1;

Student s2("zhangsan", 100);
Student* ps2 = &s2;

string Student::*pstr1 = &Student::name;
	
	
cout << s1.*pstr1 << endl;   //不同的物件可以呼叫同一個指標
cout << ps1->*pstr1 << endl;
cout << s2.*pstr1 << endl;   
cout << ps2->*pstr1 << endl;

指向類成員的指標用的不多,一般用的較多的是指向類成員函式的指標

返回值型別 (類名::*ptr)(函式引數) = &類名:: 成員函式

void (Student::*pdis)(int) = &Student::dis;

呼叫方法與成員物件指標類似: 因為優先順序問題要加上括號

(s1.*pdis)(10);
(ps1->*pdis)(20);

以下提供兩個成員函式指標的案例

#include <iostream>
using namespace std;

struct Point
{
	int add(int x, int y) {
		return x + y;
	}

	int minNus(int x, int y) {
		return x - y;
	}

	int multi(int x, int y) {
		return x * y;
	}

	int div(int x, int y) {
		return x / y;
	}
}; 

//提供公共介面
int oper(Point& p, int(Point::*pp)(int, int), int x, int y) {  //指向函式成員的指標
	return (p.*pp)(x, y);
}

typedef int(Point::*PF)(int, int);

int main() {

	Point p;
	PF padd = &Point::add;
	cout << oper(p, padd, 10, 20) << endl;

	padd = &Point::minNus;
	cout << oper(p, padd, 500, 20) << endl;
	system("PAUSE");
}

在這個案例中,我們使用成員函式指標實現了一個公共介面

#include <iostream>
using namespace std;

class Game {
public:
	Game() {
		PSkill[0] = &Game::SkillOne;
		PSkill[1] = &Game::SkillTwo;
		PSkill[2] = &Game::SkillThree;
		PSkill[3] = &Game::SkillFour;
	}

	void select(int index) {
		if (index >= 0 && index <= 3) {
			(this->*PSkill[index])();
		}
	}

private:
	void SkillOne() { cout << "Use skill one.." << endl; }
	void SkillTwo() { cout << "Use skill Two.." << endl; }
	void SkillThree() { cout << "Use skill Three.." << endl; }
	void SkillFour() { cout << "Use skill Four.." << endl; }

	enum {
		NC = 4   //技能數量
	};

	void (Game::*PSkill[NC])();
};

int main() {


	Game newOne;
	newOne.select(2);
	newOne.select(0);
	newOne.select(3);

	system("PAUSE");
}

這個案例中,假設我們不想讓外界知道類內部的函式名,我們可以是用指向成員函式的指標陣列將它們封裝起來,加強了隱蔽性