- 浏览: 399757 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (309)
- xaml C# wpf (0)
- scala java inner clas (1)
- Tools UML Eclipse UML2 (1)
- Timer .NET Framework (1)
- perl (6)
- python function paramter (1)
- Python Docstring (1)
- Python how to compare types (1)
- Python (8)
- java (5)
- C# (76)
- C# WPF (0)
- p4 (0)
- WPF (46)
- .net (6)
- xaml (1)
- javascript (40)
- windows (10)
- scala (4)
- winform (1)
- c++ (48)
- tools (12)
- cmd (1)
- os (0)
- CI (0)
- shell (0)
- C (2)
- haskell (49)
- functional (1)
- tool (1)
- gnu (1)
- linux (1)
- kaskell (0)
- svn (0)
- wcf (3)
- android (1)
最新评论
you can define members to class members, either classes data members or class method members.
there is onething that makes the pionter to member function different from other normal ponters.
A pointer to member function must first be bound to an object or a pionter to obtain a this pointer for function invocation before the function to which it refers can be called.
The type of the Pionter to data member is as follow.
// below shows you how to define // "a pointer to member of class Screen of type short." // short Screen::*
and below shows some declaration of pointer to data members to class Screen.
int Screen::*ps_Screen = &Screen::_height; ps_Screen = &Screen::_width;
and if you wan to declare some pointer to member methods.
// if you want to declare // a pointer to Screen member function capaple of referring to the mbme rfunction height() and width() is as follow int (Screen::*) (); // e.g. int (Screen::*pmf1)() = 0; int (Screen::*pmf2)() = &Screen::height; pmf1 = pmf2; pmf2 = &Screen::width;
the pointer to member functions are types, which you can typedef to something else, here is the code.
typedef Screen& (Screen::*Action)(); Action _default = &Screen::home; Action next = &Screen::forward;
As we said before, to invoke a pionter to member function, you should have a class object or pointer to to obtain the 'this' pointer, here is a simple case from the client's perspective on how to invoke the pointer to member function.
// below shows how you can invoke method through the pointer to member methods Screen myScreen; typedef Screen& (Screen::*Action)(); Action _default = &Screen::home; extern Screen& action(Screen&, Action = &Screen::display); void ff() { action(myScreen); action(myScreen, _default); action(myScreen, &Screen::end); }
Below is the code that shows you how to invoke the pionter to member functions from the devloper's perspective.
//invocation of the pointer to class member // int (Screen::*pmfi) () = &Screen::height; Screen& (Screen::*pmfS)(const Screen&) = &Screen::copy; Screen myScreen, *bufScreen; // direct invocation of the member function if (myScreen.height() == bufScreen->height() ) bufScreen->copy(myScreen); // equivalent invocation through the pointer to member function if ( (myScreen.*pmfi)() == (bufScreen->*pmfi()()) { (bufScreen->*pmfS)(myScreen); }
Similarily , you can expect the following works for the pionter to data members.
typedef int Screen::*ps_Screen; Screen myScreen, *tmpScreen = new Screen(10, 10); ps_Screen pH = &Screen::_height; ps_Screen pW = &Screen::_width; tempScreen->*pH = myScreen.*pH; tempScreen->*pW = myScreen.*pW;
With the help of Pointer to member functions, you can abtract and simplifies your code greatly, suppose we have a move method for the Screen class, and the move method should performs various action, instead of writting a huge switch case, you can do this:
class Screen { private: typedef Screen& (Screen::*Action)(); //Action (*Menu)[6]; // this is a pointer to pionter to an array of 6 //Action *Menu[6]; // this is a array of pointer, size of 6, the same as Action (*Menu[6]); static Action Menu[6]; enum CursorMovements { HOME, FORWARD, BACK, UP, DOWN, END }; public: // below we are going to show the importance of the function as pointer to members Screen& repeat(Action op, int times); Screen& move(CursorMovements cm); } Screen::Action Screen::Menu[6] = { &Screen::home, &Screen::forward, &Screen::back, &Screen::up, &Screen::down, &Screen::end }; inline Screen& Screen::repeat(Action op, int times) { for (int i = 0; i < times; ++i) { (this->*op)(); } return *this; } inline Screen& Screen::move(CursorMovements cm) { return (this->*Menu[cm])(); }
the complete code is as follow.
#include <string> #include <iostream> #include <fstream> #include <functional> #include <iterator> #include <algorithm> #include <cstring> using std::string; using std::fstream; using std::copy; using std::cout; using std::endl; using std::cerr; using std::strcpy; using std::strcat; using std::istream; using std::ostream; namespace { class Screen { private: typedef Screen& (Screen::*Action)(); //Action (*Menu)[6]; // this is a pointer to pionter to an array of 6 //Action *Menu[6]; // this is a array of pointer, size of 6, the same as Action (*Menu[6]); static Action Menu[6]; enum CursorMovements { HOME, FORWARD, BACK, UP, DOWN, END }; public: // constructor inline Screen(int hi = 8, int wid = 40, char bk = '*'); inline Screen& home() { _cursor = 0; return *this; } void move(int, int); void move(int , int ) const; char get() { return _screen[_cursor]; } inline char get(int, int ); bool checkRange(int, int) const; int height() { return _height; } int width() { return _width;} // inline Screen& forward(); inline Screen& back(); inline Screen& end(); inline Screen& up(); inline Screen& down(); inline int row(); // not defined, we might go to that later. friend istream& operator >>(istream &, Screen &) ; friend ostream& operator <<(ostream&, const Screen &) ; void copy(const Screen & obj); inline void set(const string &s); inline void set(char s); // below we are going to show the importance of the function as pointer to members Screen& repeat(Action op, int times); Screen& move(CursorMovements cm); private: inline int remainingSpace(); string _screen; // from the above declaration below, to allow the move method to be called from a const object //string::size_type _cursor; mutable string::size_type _cursor; int _height; int _width; /*static const int _height = 24; static const int _width =80;*/ static const int BELL = '\007'; }; void Screen::copy(const Screen &obj) { /// fif this Screen object and objs are the same objcet // no copy necessary /// we look at hte 'this ' pointer if (this != &obj) { _height = obj._height; _width =obj._width; _cursor = 0; // create a new string // its content is the same as obj._screen _screen = obj._screen; } } bool Screen::checkRange(int row, int col) const { if (row < 1 || row > _height || col < 1 || col > _width ) { cerr << "Screen coordinates (" << row << ", " << col << " ) out of bounds.\n"; return false; } return true; // a better way is to write as such //return !((row < 1 || row > _height || col < 1 || col > _width)); } inline void Screen::move(int r, int c) { // move _cursor to absolute position if (checkRange(r, c) ) { int row = ( r - 1) * _width; // row location _cursor = row + c - 1; } } inline void Screen::move(int r, int c) const { // can we directly call the Screen::move method or can we ask the Screen::move(int r, int c) to call the (Screen::move(int r, int c) const" method if (checkRange(r, c)) { int row = (r - 1) * _width; _cursor = row + c - 1; // because now the _cursor is mutable members, it does not matter if you call it from a const contetxt } } // a side note, inline declaration should be placed // in the header file. normally you will carry the inline keyword with you . inline char Screen::get(int r, int c) { move(r, c); return get(); } inline void Screen::set(const string &s) { // write string beginning at current _cursor position int space = remainingSpace(); int len = s.size(); if (space < len) { cerr << "Screen: warning: truncate: " << "space: " << space << "string length: " << len << endl; } } inline void Screen::set(char ch) { if (ch == '\0') { cerr << "Screen: Warning: " << "Null character (ignored).\n"; } else { _screen[_cursor] = ch; } } inline int Screen::remainingSpace() { // currrent position is no longer remaining int sz = _width * _height; return (sz - _cursor); } inline Screen::Screen(int hi, int wid, char bk) : _height (hi), _width(wid), _cursor(0), _screen(hi * wid, bk) { // all the work is done with the number initialize list } Screen::Action Screen::Menu[6] = { &Screen::home, &Screen::forward, &Screen::back, &Screen::up, &Screen::down, &Screen::end }; inline Screen& Screen::forward() { ++_cursor; // check if top of screen: wrap around if (_cursor == 0) { home(); } return *this; } inline Screen& Screen::back() { // move _cursor backward one screen element // check for opt of screen: wrap around if (_cursor == 0) { end(); } else --_cursor; return *this; } inline Screen& Screen::end() { _cursor = _width * _height - 1; return *this; } inline Screen& Screen::up() { // move _cursor up one row of screen // do not wrap around; rather, ring bells if (row() == 1) // at top ? cout << BELL << endl; else _cursor -= _width; return *this; } inline Screen& Screen::down() { if (row() == _height) // at bottom? cout << BELL << endl; else _cursor += _width; return *this; } inline int Screen::row() { return (_cursor + _width) / _width; } inline Screen& Screen::repeat(Action op, int times) { for (int i = 0; i < times; ++i) { (this->*op)(); } return *this; } inline Screen& Screen::move(CursorMovements cm) { return (this->*Menu[cm])(); }
发表评论
-
不安装Visual Studio,只用Windows SDK搭建VC环境
2013-12-31 21:52 15342首先你需要下载的是 Microsoft Windows S ... -
rpath - runtime search path
2013-04-03 11:36 1012RPath is a very interesting to ... -
C++ - autogenerated copy constructor and assignment operator gotchas
2013-01-24 13:32 772It has been changed that the s ... -
c++ - rethrow a exception gotchas
2012-12-23 10:57 963As in my prevoius example in j ... -
c++ -typeid operator
2012-10-15 22:30 1060typeid is the one of the meager ... -
c++ - dynamic_cast revisit
2012-10-14 21:21 771There are several built-in type ... -
c++ - virtual inheritance example 1
2012-10-14 15:25 823we have discussed the virtual i ... -
c++ - virtual inheritance
2012-10-12 08:58 977As we have discussed in the pos ... -
c++ type of inheritance
2012-09-28 08:58 754There are 3 types of inheritanc ... -
c++ - vritually virtual new
2012-09-27 23:59 960Let's see what if we want to cl ... -
c++ - virtual destructor
2012-09-27 22:01 975As we all know that virtual des ... -
c++ - vritual function and default arguments
2012-09-27 08:56 994As we all know that we virtual ... -
c++ - template specialization and partial specialization
2012-09-26 22:38 1328in this post, we are going to e ... -
c++ - member template in class template
2012-09-26 08:19 939class member template can be us ... -
c++ template class and the pattern to use its friends
2012-09-25 23:47 986template class may defined thei ... -
c++ - Friend declaration in class Template
2012-09-25 08:47 1212There are three kinds of friend ... -
c++ - class template default parameters
2012-09-25 08:18 854the template has parameter, it ... -
c++ - operator new and delete and an example of linked list stores by new/delete
2012-09-24 07:53 588The operator new and delete ope ... -
c++ - delete(void *, size_t) or delete(void *)
2012-09-24 07:18 1170In my previous dicuss, we have ... -
c++ - placement operator new() and the operator delete()
2012-09-23 15:22 873A class member operator new() c ...
相关推荐
Keeping up-to-date with the language helps take advantage of new features and improvements. #### Header Files - **Self-contained Headers:** Each header file should include everything necessary for ...
- **Value Classes**: Section 8.9 provides an overview of value classes, which are similar to structs in C++. - **Interfaces**: Section 8.10 covers interfaces, which define contracts for classes to ...
Scoping Namespaces Nested Classes Nonmember, Static Member, and Global Functions Local Variables Static and Global Variables Classes Doing Work in Constructors Default Constructors Explicit ...
The book is structured into chapters that cover various aspects of C++, from the basics to more advanced topics. Here, we will summarize the key points and concepts from each chapter: ### Chapter 1:...
- **Non-member, Static Member, and Global Functions**:非成员函数、静态成员函数和全局函数应当尽量避免使用,除非它们对于程序的功能是必需的。 - **Local Variables**:局部变量应当尽可能地在最短的作用域内...
Classes**:结构体(struct)和类(class)在C++中有不同的默认访问级别,应根据实际需求选择合适的类型。 - **Inheritance**:继承是一种强大的机制,但也可能带来复杂性和难以维护的问题,因此需要谨慎使用。 -...
Classes**:在C++中,struct和class的区别主要在于默认访问权限不同,通常struct用于表示数据结构,而class用于实现抽象的数据类型。 - **Inheritance**:继承是面向对象编程的核心概念之一,应谨慎使用以避免复杂...
Classes**:在C++中,`struct`和`class`非常相似,主要区别在于`struct`默认成员访问权限为`public`,而`class`默认成员访问权限为`private`。选择使用哪种取决于具体的场景需求。 ##### 4. **Functions(函数)**...
// the Standard C++ Library basic_string<> template and add to it the // the following conveniences: // - The full MFC CString set of functions (including implicit cast) // - writing to/reading ...
- **Pointer-to-Member Representation**:成员指针表示方式,控制类内部成员指针的存储格式。包括: - **Best-Case Always**:采用最佳情况下始终一致的方式表示。 - **General-Purpose Always**:通用方式始终...
7.3 Function-to-pointer conversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 7.4 Temporary materialization conversion . . . . . . . . . . . . . . . . . . . . . . . . . . ....
76-78 结构指针(Pointers to structures) -> 这是一个引用操作符,常与结构或类的指针一起使用,以便引用其中的成员元素,这样就避免使用很多括号。例如,我们用: pmovie->title 来代替: (*pmovie).title 79 ...
### Google C++代码规范详解 #### 一、头文件 **1. #define的保护** 在C++中,为了防止同一个头文件被多次包含导致重复定义的问题,通常会在头文件的开头和结尾处使用`#ifndef`/`#define`/`#endif`这样的预处理器...
- **Non-member, Static Member, and Global Functions**:非成员函数、静态成员函数和全局函数都有各自的适用场景。全局函数应尽量避免使用,以减少命名冲突和提高模块化程度。 - **Local Variables**:局部变量只...
- **`->`:** Pointer-to-member access. - **`++`, `--`:** Increment/decrement. - **`+`, `-`, `~`, `!`:** Unary plus, minus, bitwise NOT, logical NOT. - **`(type)`:** Cast (convert). - **`*`, `/`, `...
stdafx.h的代码// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a ...