关于解引用*和箭头操作符->的重载

这里以一个智能指针类为例,智能指针所指为一个对象。

而事实上,STL迭代器的开发均需要重载这两个操作符,上一篇文章分析STL 迭代器中除了要用到template技巧外,还需要重载技巧

  1.  1 #include<iostream>
     2 using namespace std;
     3 class Screen
     4 {
     5
     6 public:
     7     friend ostream& operator<<(ostream&os, Screen &s);
     8     int action(){ return ++data; }
     9     Screen(int i = 0) :data(i){}
    10 private:
    11     int data;
    12 };
    13 ostream& operator<<(ostream&os, Screen &s)
    14 {
    15     os << s.data;
    16     return os;
    17 }
    18 class U_ptr
    19 {
    20     friend class ScreenPtr;
    21     Screen* p;
    22     size_t use;
    23     U_ptr(Screen *pp) :p(pp), use(1){}
    24     ~U_ptr(){ delete p; }
    25 };
    26 class ScreenPtr
    27 {
    28 private:
    29     U_ptr *ptr;
    30 public:
    31     ScreenPtr(Screen *p) :ptr(new U_ptr(p)){}
    32     ScreenPtr(ScreenPtr &orgi_p) :ptr(orgi_p.ptr){ ++ptr->use; }
    33     ~ScreenPtr(){ if (--ptr->use == 0)delete ptr; }
    34     Screen& operator*()
    35     {
    36         return *(ptr->p);
    37     }
    38     Screen* operator->()
    39     {
    40         return ptr->p;
    41     }
    42 };
    43 class gao
    44 {
    45 private:
    46     ScreenPtr *p;
    47 public:
    48     gao(ScreenPtr* q) :p(q){}
    49     ScreenPtr& operator->()
    50     {
    51         return *p;
    52     }
    53 };
    54 int main()
    55 {
    56
    57     ScreenPtr ptr(new Screen(5));
    58     cout << "*操作符  " << *ptr << endl;
    59     cout << "->操作符  " << ptr->action() << endl;
    60     ScreenPtr* pp = &ptr;
    61     gao d(pp);
    62     cout << "!" << d->action() << endl;
    63     system("pause");
    64 }

这里的代码逻辑如下:

1. 首先定义一个简单封装的U_ptr,其实就是指向Screen的指针+一个引用计数的封装

2. 然后定义真正的智能指针类ScreenPtr,其成员是U_ptr,

3. 然后定义构造函数和复制构造函数(对引用计数++)

4. 再定义析构函数,只有当--use==0时才进行析构,调用U_ptr类的析构函数

5. 最后,为了使类ScreenPtr 具有指针类似的表现,重载operator* 和 ->

*是一个一元操作符,作为成员函数故无形参,返回的是指向Screen的引用

->是一个一元操作符,尽管长得像二元操作符,故也无形参。

这里应该格外注意,为什么其返回值是一个Screen的指针?

可以这样理解,

      对于一个指针类型变量p,p->action()表示返回其成员       //action()为Screen类的成员函数

而对于我们想要重载的类ScreenPtr而言,调用->的是ScreenPtr的对象,因此这里返回一个指向Screen的指针,然后编译器会自动绑定其成员,也就是说ScreenPtr对象 sp->action()的含义为    ( sp.operator->() )->action())

更一般的,->重载后返回值除了返回一个指针外,还可以返回一个已经重载了->操作符的类对象的引用,然后编译器递归调用重载过的->,直到有一个返回指针,如上面的类gao

关于解引用*和箭头操作符->的重载,布布扣,bubuko.com

时间: 2024-10-24 11:42:35

关于解引用*和箭头操作符->的重载的相关文章

操作符重载之解引用与箭头操作符

箭头操作符与众不同.它可能表现得像二元操作符一样:接受一个对象和一个成员名,对对象解引用以获取成员.不管外表如何,箭头操作符不接受显式形参.这里没有第二个形参,因为 -> 的右操作数不是表达式,相反,是对应着类成员的一个标识符.没有明显可行的途径将一个标识符作为形参传递给函数,相反,由编译器处理获取成员的工作. 理解1 当这样编写时:point->action();由于优先级规则,它实际等价于编写:(point->action)();换句话说,我们想要调用的是对 point->ac

[转载] C++重载箭头操作符

转自:http://www.cppblog.com/custa/archive/2010/08/15/123491.html 今天看<C++ Primer>的成员访问操作符.看重载箭头操作符部分,刚开始有点迷茫,看了两遍总算有点理解,把心得写在这,与各位分享,如果有错误欢迎指正. 箭头操作符(->)的通常用法是,使用一个类对象的指针来调用该指针所指对象的成员.左操作数为对象指针,右操作数为该对象的成员.定义重载箭头操作符之后看起来就有点特别,可以用类对象的指针来调用,也可以用类对象直接调

C++学习之路: 特殊操作符-&gt;的重载

转自:http://blog.csdn.net/custa/article/details/5674434 primer 书上对重载该操作符的解释过于简单,但是总结性十分强: 重载箭头操作符必须返回指向类类型的指针,或者返回定义了自己的箭头操作符的类类型对象. 如果返回类型是指针,则内置箭头操作符可用于该指针,编译器对该指针解引用并从结果对象获取指定成员.如果被指向的类型没有定义那个成员,则编译器产生一个错误. 如果返回类型是类类型的其他对象(或是这种对象的引用),则将递归应用该操作符.编译器检

【C++ Primer每日一刷之十二】 箭头操作符,条件操作符,sizeof操作符,逗号,优先级

5.6. 箭头操作符 C++ 语言为包含点操作符和解引用操作符的表达式提供了一个同义词:箭头操作符(->).点操作符(第 1.5.2 节)用于获取类类型对象的成员: item1.same_isbn(item2); // run thesame_isbn member of item1 如果有一个指向 Sales_item 对象的指针(或迭代器),则在使用点操作符 前,需对该指针(或迭代器)进行解引用: Sales_item *sp = &item1; (*sp).same_isbn(item

C++14 SFINAE 解引用迭代器

C++14 SFINAE 解引用迭代器 p { margin-bottom: 0.25cm; line-height: 120% } a:link { } 原问题:编写函数f(r),若r为迭代器,则返回f(*r),否则返回r. p { margin-bottom: 0.25cm; line-height: 120% } a:link { } 摘要: p { margin-bottom: 0.25cm; line-height: 120% } a:link { } 问题: 什么是迭代器? 迭代器是

解引用NULL指针

一般导致程序崩溃的最重要原因之一就是试图解引用NULL指针.正如上几篇文章中所说的,智能指针RefCountPtr和ScopedPtr提供了运行时的诊断.但是,并不是所有的指针都是拥有某个对象所有的智能指针.因此为了对试图解引用一个不具有对象所有权的指针的行为进行诊断,引入一种并不删除它所指向的对象的"半智能"指针.例如,如下代码示例: template <typename T> class Ptr { public: explicit Ptr(T* p = NULL) :

数组操作符的重载(二十八)

我们在学习了 string 类对象后,就不禁头脑中冒出了一个问题:string 类对象还具备 C 方式字符串的灵活性吗?还能直接访问单个字符吗?那么 string 类最大限度的考虑了 C 字符串的兼容性,可以按照使用 C 字符串的方式使用 string 对象. 下来我们用 C 方式使用 string 类,看看示例代码 #include <iostream> #include <string> using namespace std; int main() {     string 

C++点和箭头操作符用法区别

C++点和箭头操作符用法区别 变量是对象的时候用“.”访问 变量是对象指针的时候用“->”访问 例: #inlclude <iostream> using namespace std; class A {     public:        int x;        int y;  }; int main() {       A a;       a.x=100;        //对象用点访问       // a->y=100;     //error       A* p

谈谈ES6箭头操作符

如果你会C#或者Java,你肯定知道lambda表达式,ES6中新增的箭头操作符=>便有异曲同工之妙.它简化了函数的书写.操作符左边为输入的参数,而右边则是进行的操作以及返回的值Inputs=>outputs. 我们知道在JS中回调是经常的事,而一般回调又以匿名函数的形式出现,每次都需要写一个function,甚是繁琐.当引入箭头操作符后可以方便地写回调了.请看下面的例子. var array = [1, 2, 3]; //传统写法 array.forEach(function(v, i, a