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


    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;
    }
    

  • 相关阅读:
    2018-2019-1 20189221 《从问题到程序》第 6 周学习总结
    2018-2019-1 20189221 《Linux内核原理与分析》第七周作业
    《文献管理与信息分析》第 2 周学习总结
    2018-2019-1 20189221 《从问题到程序》第 5 周学习总结
    2018-2019-1 20189221 《Linux内核原理与分析》第六周作业
    2018-2019-1 20189206 《深入理解计算机系统》第一章学习笔记
    2018-2019-1 20189206 《从问题到程序》速读
    2018-2019-1 20189206 《深入理解计算机系统》速读
    2018-2019-1 20189206 《构建之法》速读
    2018-2019-1 20189206 《Linux内核原理与分析》第二周作业
  • 原文地址:https://www.cnblogs.com/mydomain/p/2054531.html
Copyright © 2020-2023  润新知