37、C++ Primer 4th笔记,特殊工具与技术,类成员指针

简介: 1、成员指针(pointer to member)包含类的类型以及成员的类型。成员指针只应用于类的非static成员。static类成员不是任何对象的组成部分,所以不需要特殊语法来指向static成员,static成员指针是普通指针。

1、成员指针(pointer to member)包含类的类型以及成员的类型。成员指针只应用于类的非static成员。static类成员不是任何对象的组成部分,所以不需要特殊语法来指向static成员,static成员指针是普通指针。通过指定函数的返回类型,形参表(类型和数目,是否为const)和所属类来定义成员函数的指针。

2、使用类成员的指针

    类似于成员访问操作符 . ->.* -> 是两个新的操作符,它们使我们能够将成员指针绑定到实际对象。这两个操作符的左操作数必须是类类型的对象或类类型的指针,右操作数是该类型的成员指针。

• 成员指针解引用操作符.*从对象或引用获取成员。

• 成员指针箭头操作符->*通过对象的指针获取成员。

示例代码

#include "iostream"
#include "string"
#include "vector"

using namespace std;

class Screen
{
public:
	Screen(std::string StrCon = "Here", std::string::size_type myCursor = 12):contents(StrCon), cursor(myCursor){}
	typedef std::string::size_type index;
	char get() const{return '1';};
	char get(index ht, index wd) const{return '2';};
public:
	std::string contents;
	index cursor;
	index height, width;
};

int main()
{
	//定义的成员指针从右向左读
	string Screen::*ps_Screen = &Screen::contents; 
	char (Screen::*pmf)() const = &Screen::get;
	char (Screen::*pmf1)(Screen::index,Screen::index) const = &Screen::get;
	Screen myScreen;
	
	//使用成员函数的指针
	char c1 = myScreen.get();
	char c2 = (myScreen.*pmf)();
	cout << c1 << " " << c2 << endl; // 1  1
	Screen *pScreen = &myScreen;
	c1 = pScreen->get();
	c2 = (pScreen->*pmf)();
	cout << c1 << " " << c2 << endl; // 1  1
	c1 = pScreen->get(0, 0);
	c2 = (pScreen->*pmf1)(0, 0);
	cout << c1 << " " << c2 << endl; // 2  2

	//使用数据成员的指针
	Screen::index Screen::*pIndex = &Screen::cursor;
	Screen::index ind1 = myScreen.cursor;
	Screen::index ind2 = myScreen.*pIndex;
	cout << ind1 << " " << ind2 << endl;
	return 1;
}

注意: (myScreen.*pmf)();不能省略括号。因为()的优先级比*高,所以如果省略括号,则解析成:myScreen.*(pmf());这段代码的意思是:调用名为pmf的函数,把函数的返回值绑定到成员对象操作符(.*)的指针。

2)成员指针函数表

函数指针和成员函数指针的一个公共用途是,将它们存储在函数表中。函数表是函数指针的集合,在运行时从中选择给定调用。

示例代码

#include "iostream"
#include "string"
#include "vector"

using namespace std;

class Screen {
public:
	// other interface and implementation members as before
	//Screen& home(){}; // cursor movement functions
	//Screen& forward(){};
	//Screen& back(){};
	//Screen& up(){};
	//Screen& down(){};
	int home() {return 1;}
	int forward(){return 1;}
	int back() {return 1;}
	int up(){return 1;}
	int down(){return 1;}
public:
	// other interface and implementation members as before
	// Action is pointer that can be assigned any of the cursor movement members
	//typedef Screen& (Screen::*Action)();
	typedef int (Screen::*Action)();
	static Action Menu[]; // function table
public:
	// specify which direction to move
	enum Directions { HOME, FORWARD, BACK, UP, DOWN };
	Screen& move(Directions);
};
Screen& Screen::move(Directions cm)
{
	// fetch the element in Menu indexed by cm
	// run that member on behalf of this object
	(this->*Menu[cm])();
	return *this;
}
Screen::Action Screen::Menu[] = 
{ 
	&Screen::home,
	&Screen::forward,
	&Screen::back,
	&Screen::up,
	&Screen::down,
};
int main()
{
	Screen myScreen;
	myScreen.move(Screen::HOME); // invokes myScreen.home
	myScreen.move(Screen::DOWN); // invokes myScreen.down
	return 1;
}

3、枚举的大小

示例代码

#include "iostream"
#include "string"
#include "vector"

using namespace std;
class A
{
public:
	enum MyData{M1, M2, M3, M4};
	static int iMy;
};
int A::iMy = 1;
enum MyData{M1, M2, M3, M4};
int main()
{
	A Data1;
	cout << A::M1 << " " << A::M2 << " " << A::M3 << " "<< endl; //0 1 2
	cout << Data1.M1 << " " << Data1.M2 << " " << Data1.M3 << endl; //0 1 2
	//cout << A::MyData << endl; //“A::MyData”: 将此类型用作表达式非法
	cout << sizeof(A) << endl; //1
	cout << sizeof(Data1) << endl; //1

	cout << sizeof(MyData) << endl; //4
	MyData Data2;
	cout << sizeof(Data2) << endl; //4
	return 1;
}

枚举的大小为一个整形数据的大小。但是,在类中,求类的大小时,不计算数据成员的大小,同样也不计算枚举成员的大小。类中定义的枚举数据成员可以通过类名和作用域直接引用。

http://www.cnblogs.com/mydomain/archive/2011/04/30/2033483.html

4、我们需要注意的是,静态函数没有this指针。但是,类和类对象共享一份类中定义的静态数据成员。在非静态函数中可以通过this指针来引用这些静态数据成员。

示例代码

#include "iostream"
#include "string"
#include "vector"

using namespace std;
class A
{
public:
	void Print()
	{
		cout << this->iMy << endl;
	}
public:
	static int iMy;
};
int A::iMy = 1;
int main()
{
	A Data1;
    Data1.Print(); //1
	cout << A::iMy << endl; //1
	Data1.iMy = 2;
	A Data2;
	cout << Data2.iMy << endl; //2
	return 1;
}

http://www.cnblogs.com/mydomain/archive/2011/03/22/1991449.html

5、函数指针的赋值

示例代码

#include <iostream>
using namespace std;

char myfun()
{
	return '1';
}
char* myfun2()
{
	char *p = (char*)malloc(3);
	return p;
}

int main()
{
	char (*p)() = myfun;
	//char* (p1()) = &myfun2; //error,无法从“char *(__cdecl *)(void)”转换为“char *(void)
	char* (*p1)() = &myfun2;
	//char *p() = myfun(); //注意,这样做是错误的,p被定义为一个函数,返回char*,而不是函数指针。
	return 1;
}
目录
相关文章
|
16天前
|
存储 安全 编译器
在 C++中,引用和指针的区别
在C++中,引用和指针都是用于间接访问对象的工具,但它们有显著区别。引用是对象的别名,必须在定义时初始化且不可重新绑定;指针是一个变量,可以指向不同对象,也可为空。引用更安全,指针更灵活。
|
1月前
|
存储 C++
c++的指针完整教程
本文提供了一个全面的C++指针教程,包括指针的声明与初始化、访问指针指向的值、指针运算、指针与函数的关系、动态内存分配,以及不同类型指针(如一级指针、二级指针、整型指针、字符指针、数组指针、函数指针、成员指针、void指针)的介绍,还提到了不同位数机器上指针大小的差异。
33 1
|
1月前
|
存储 编译器 C语言
C++入门2——类与对象1(类的定义和this指针)
C++入门2——类与对象1(类的定义和this指针)
24 2
|
1月前
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
1月前
|
存储 C++ 索引
C++函数指针详解
【10月更文挑战第3天】本文介绍了C++中的函数指针概念、定义与应用。函数指针是一种指向函数的特殊指针,其类型取决于函数的返回值与参数类型。定义函数指针需指定返回类型和参数列表,如 `int (*funcPtr)(int, int);`。通过赋值函数名给指针,即可调用该函数,支持两种调用格式:`(*funcPtr)(参数)` 和 `funcPtr(参数)`。函数指针还可作为参数传递给其他函数,增强程序灵活性。此外,也可创建函数指针数组,存储多个函数指针。
|
1月前
|
存储 编译器 程序员
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(二)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
5月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
1月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
20 0
|
2月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
|
3月前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)