首页 > 技术文章 > C/C++ 类成员函数指针 类成员数据指针

xuaidongstdudyrecording 2017-07-29 15:32 原文

普通函数指针:  "return_type (*ptr_name)(para_types) "

类成员函数指针: "return_type (class_name::*ptr_name)(para_types)"

类数据成员指针: "type class_name::* ptr_name";

 

C/C++:

 1 class Demo
 2 {
 3 public:
 4     Demo():data(100)
 5     {
 6 
 7     }
 8     int data;
 9     int show(int a,int b)
10     {
11         return a+b;
12     }
13 };
14 
15 
16 
17 int main(int argc, char **argv)
18 {
19     Demo A;
20     Demo* B=new Demo;
21     //完成声明和赋值
22     int Demo::* int_ptr=&Demo::data;
23     //赋值完后没有数据信息,需要对象解引用获得数据
24     std::cout<<A.*int_ptr<<std::endl;
25     std::cout<<B->*int_ptr<<std::endl;
26 
27     
28     //类成员函数指针
29     int (Demo::*ptr)(int,int)=&Demo::show;
30     std::cout<<(A.*ptr)(1,2)<<std::endl;
31 
32     return 0;
33 }


 

 

 

STL算法有时需要使用类成员的函数,然而类成员函数指针不是可调用对象,functor<> bind mem_fn 各自方式不一,但是内部都是隐式传递this指针通过解引用来获取数据或调用函数

 

C/C++扩展:

  1 //成员函数指针使用
  2 
  3 class Screen
  4 {
  5 public:
  6     enum ACTION
  7     {
  8         Up_, Down_, Left_, Right_
  9     };
 10 
 11     Screen() = default;
 12 
 13     Screen &Move(ACTION para)
 14     {
 15         return (this->*Menu[para])();
 16     }
 17 
 18 private:
 19     using Action=
 20     Screen &(Screen::*)();
 21 
 22 
 23     static Action Menu[];
 24 
 25     Screen &Up()
 26     {
 27         std::cout << "Up" << std::endl;
 28         return *this;
 29     }
 30 
 31     Screen &Down()
 32     {
 33         std::cout << "Down" << std::endl;
 34         return *this;
 35     }
 36 
 37     Screen &Left()
 38     {
 39         std::cout << "Left" << std::endl;
 40         return *this;
 41     }
 42 
 43     Screen &Right()
 44     {
 45         std::cout << "Right" << std::endl;
 46         return *this;
 47     }
 48 
 49 };
 50 
 51 Screen::Action Screen::Menu[]{&Screen::Up, &Screen::Down, &Screen::Left, &Screen::Right};
 52 
 53 
 54 int main()
 55 {
 56     Screen obj;
 57     obj.Move(Screen::Up_);
 58     obj.Move(Screen::Down_);
 59     obj.Move(Screen::Left_);
 60     obj.Move(Screen::Right_);
 61     obj.Move(Screen::Right_);
 62 
 63 
 64     return 0;
 65 }
 66 
 67 
 68 
 69 #include <iostream>
 70 #include <vector>
 71 #include <functional>
 72 #include <algorithm>
 73 #include <string>
 74 
 75 //类成员函数指针不是可调用对象,一般STL算法需要包装类成员函数指针为可调用对象
 76 //这三种封装方式都是内部通过获得容器返回的对象, ".*" / "->*" 来调用;
 77 //1.std::function<成员函数类型(第一个参数设置为对象本身类型)> fcn=&std::xxxx::xxx;   区别: 第一个参数是传入对象类型,根据容器是引用还是指针选择(.* / ->*)
 78 //2.std::bind(&std::string::empty,std::placeholders::_1) 区别:可通过指针或者对象执行成员函数;
 79 //3.std::mem_fn(&std::string::empty)  C++11, 区别:可通过指针和对象执行成员函数
 80 //4.可使用lamda调用;
 81 
 82 
 83 class Str
 84 {
 85 public:
 86     std::string str;
 87 
 88     Str(const std::string &str_) : str(str_)
 89     {
 90 
 91     }
 92 
 93     Str(const char *str_) : str(str_)
 94     {
 95 
 96     }
 97 
 98     bool empty() const noexcept
 99     {
100         return str.empty();
101     }
102 };
103 
104 
105 int main()
106 {
107 
108     std::vector<Str> str_vec{"xa", "sad", "", "", "", "qqewhegr", "aqdq"};
109 
110 
111     std::function<bool(const Str &)> fn = &Str::empty;
112 
113     std::size_t empty_size_function=std::count_if(str_vec.begin(),str_vec.end(),fn);
114 
115     std::size_t empty_size_bind=std::count_if(str_vec.begin(),str_vec.end(),std::bind(&Str::empty,std::placeholders::_1));
116 
117     std::size_t empty_size_mem_fn=std::count_if(str_vec.begin(),str_vec.end(),std::mem_fn(&Str::empty));
118 
119 
120     std::cout << empty_size_function << std::endl;
121     std::cout << empty_size_bind << std::endl;
122     std::cout << empty_size_mem_fn << std::endl;
123 
124 
125 
126     std::size_t size = std::count_if(str_vec.begin(), str_vec.end(), [](const Str& str) { return str.empty(); });
127     std::cout << size << std::endl;
128 
129 
130     return 0;
131 }

 

推荐阅读