• Thinking in C++: Pointers to members 指向成员的指针


    通常来说,一个指针(pointer)是一个存储地址的变量,你能在运行时去改变它,并且指针可以指向数据或函数。

    但在C++中,指向成员的指针(pointer-to-member)指向的是class或struct中的成员,但在class中并没有地址,所以指向成员的指针实际上是存储的偏移量(offset),你不能生成一个实际的地址直到你将某个特殊的对象的起始地址(starting address)与这个偏移量结合起来。

    //: C11:PointerToMemberData.cpp
    #include <iostream>
    using namespace std;
    class Data {
    public:
    int a, b, c;
    void print() const {
    cout << "a = " << a << ", b = " << b
    << ", c = " << c << endl;
    }
    };
    int main() {
    Data d, *dp = &d;
    int Data::*pmInt = &Data::a;
    dp->*pmInt = 47;
    pmInt = &Data::b;
    d.*pmInt = 48;
    pmInt = &Data::c;
    dp->*pmInt = 49;
    dp->print();
    } ///:~


    请注意它的语法!

    上面的例子是指向成员变量的指针,下面展示指向成员函数的指针:

    //: C11:PointerToMemberFunction.cpp
    #include <iostream>
    using namespace std;
    class Widget {
    public:
    void f(int) const { cout << "Widget::f()
    "; }
    void g(int) const { cout << "Widget::g()
    "; }
    void h(int) const { cout << "Widget::h()
    "; }
    void i(int) const { cout << "Widget::i()
    "; }
    };
    int main() {
    Widget w;
    Widget* wp = &w;
    void (Widget::*pmem)(int) const = &Widget::h;
    (w.*pmem)(1);
    (wp->*pmem)(2);
    } ///:~


    需要注意的是指向静态成员的指针(static):

    指向静态成员的指针,声明的方式和普通指针是一样的,但跟指向普通成员的指针不一样,不需要class的限定,只是赋值的时候,还得加上类的限定符。

    class A
    {
        static int _val;
        static int val();
    };
    
    int *p_val = &A::_val;
    int (*p_func) = &A::val;


    需要注意的是这个时候的指针必须在全局作用域内声明,在main函数中声明会出错。

    下面是一个结合本书和msdn上一个例子的代码:

    #include <stdafx.h>
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Data{
    public:
    	static int a;
    public:
    	int b,c;
    	void print() const{
    		cout<<"a="<<a<<",b="<<b<<",c="<<c<<endl;
    	}
    };
    
    int Data::a = 10;
    int *p = &Data::a; //static member pointer
    int Data::*p2 = &Data::b; //member pointer
    int Data::*p3 = &Data::c; //member pointer
    
    class Window
    {
    public:
    	Window();
    	Window(int x1,int y1, int x2, int y2);
    	bool SetCaption(const char *szTitle);
    	const char *GetCaption();
    	char *szWinCaption;
    };
    
    //pointer to data member
    char * Window::pwCaption = &Window::szWinCaption;
    //pointer to function member
    const char *(Window::*pfnGetCaption)()=&Window::GetCaption;
    bool (Window::*pfnSetCaption)(const char *) = &Window::SetCaption;
    
    int main(int argc, char* argv[])
    {
    	Data ddd;
    	ddd.print();
    	*p = 40;
    	ddd.*p2 = 50;
    	ddd.*p3 = 60;
    	ddd.print();
    
    
    	int tt;
    	cin>>tt;
    
    }


    这块虽然不常用,但是是很重要的一块内容,经常在面试题中出现,希望大家好好学习。



  • 相关阅读:
    sort uniq 命令 企业应用场景实战排序
    网络管理相关命令常用必回基础实战
    Zabbix 3.0入门到企业实战(自带模板介绍)
    jsp页面指令
    jsp九大内置对象
    如何将静态页面转化为动态页面
    转发与重定向区别
    cookie的保存时间
    登陆界面 实现思路
    卸载了mysql之后,mysql服务仍在,显示读取描述失败,错误代码2
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3228544.html
Copyright © 2020-2023  润新知