C++primer中重載箭頭操作符部分看得有點雲裏霧裏的。經過反覆測試,有了點眉目,爲了避免自己忘掉,記下現在的心得。因爲自己比較懶,就直接把代碼和註釋貼過來。
//////////////////////////// -----NoName.h---- //////////////////////////////////////////////
#pragma once
#include"ScreenPtr.h"
class NoName
{
public:
NoName(Screen* p):m_sp(new ScreenPtr(p))
{}
~NoName(void)
{}
private:
ScreenPtr* m_sp;
public:
ScreenPtr operator->(void)
{
return *m_sp;
}
const ScreenPtr operator->(void) const
{
return *m_sp;
}
};
//////////////////////////// -----ScrPtr.h---- //////////////////////////////////////////////
#pragma once
#include"Screen.h"
class ScrPtr
{
friend class ScreenPtr;
ScrPtr(Screen* p):sp(p), count(1)
{}
~ScrPtr(void)
{
delete sp;
}
Screen* sp;
size_t count;
};
//////////////////////////// -----Screen.h---- //////////////////////////////////////////////
#pragma once
#include<iostream>
using namespace std;
class Screen
{
public:
Screen(void):cursor(0), height(0), width(0)
{}
~Screen(void)
{}
typedef string::size_type index;
private:
string contents;
index cursor;
index height, width;
public:
friend ostream& operator<<(ostream& os, const Screen& scr)
{
os << scr.cursor << '/t' << scr.height << '/t' << scr.width;
return os;
}
index get_cursor(void)
{
return cursor;
}
};
//////////////////////////// -----ScreenPtr.h---- //////////////////////////////////////////////
#pragma once
#include"ScrPtr.h"
class ScreenPtr
{
public:
ScreenPtr(Screen* p);
~ScreenPtr(void);
private:
ScrPtr* m_sptr;
public:
ScreenPtr(const ScreenPtr& orig);
ScreenPtr& operator=(ScreenPtr& rhs);
Screen& operator*(void);
const Screen& operator*(void) const;
Screen* operator->(void);
const Screen* operator->(void) const;
};
#include "ScreenPtr.h"
ScreenPtr::ScreenPtr(Screen* p):m_sptr(new ScrPtr(p))
{
}
ScreenPtr::~ScreenPtr(void)
{
if(-- m_sptr->count == 0)
delete m_sptr;
}
ScreenPtr::ScreenPtr(const ScreenPtr& orig):m_sptr(orig.m_sptr)
{
++ m_sptr->count;
}
ScreenPtr& ScreenPtr::operator=(ScreenPtr& rhs)
{
//TODO: insert return statement here
if(-- m_sptr->count == 0)
delete m_sptr;
++ rhs.m_sptr->count;
m_sptr = rhs.m_sptr;
return *this;
}
//////////////////////////// -----ScreenPtr.cpp---- //////////////////////////////////////////////
#include "ScreenPtr.h"
ScreenPtr::ScreenPtr(Screen* p):m_sptr(new ScrPtr(p))
{
}
ScreenPtr::~ScreenPtr(void)
{
if(-- m_sptr->count == 0)
delete m_sptr;
}
ScreenPtr::ScreenPtr(const ScreenPtr& orig):m_sptr(orig.m_sptr)
{
++ m_sptr->count;
}
ScreenPtr& ScreenPtr::operator=(ScreenPtr& rhs)
{
//TODO: insert return statement here
if(-- m_sptr->count == 0)
delete m_sptr;
++ rhs.m_sptr->count;
m_sptr = rhs.m_sptr;
return *this;
}
Screen& ScreenPtr::operator*(void)
{
//TODO: insert return statement here
return *m_sptr->sp;
}
const Screen& ScreenPtr::operator*(void) const
{
//TODO: insert return statement here
return *m_sptr->sp;
}
Screen* ScreenPtr::operator->(void)
{
return m_sptr->sp;
}
const Screen* ScreenPtr::operator->(void) const
{
return m_sptr->sp;
}
//////////////////////////// -----main.cpp---- //////////////////////////////////////////////
#include<iostream>
//#include"Person.h"
#include"Screen.h"
#include"ScreenPtr.h"
#include"ScrPtr.h"
#include"NoName.h"
//#include"Sales_item.h"
//#include<vector>
//#include"SmartPtr.h"
//#include"HasPtr.h"
using namespace std;
void main()
{
Screen* scr = new Screen;
ScreenPtr pscr(scr);
cout << *pscr << endl;
ScreenPtr pscr2(pscr);
// cout << (pscr2.operator ->())->get_cursor() << endl; // 該行與下一行等價 // ->get_cursor() “內置”-> 操作符
// “內置”箭頭操作符作用於返回的指針
// cout << pscr2->get_cursor() << endl; // 調用“重載”->操作符
cout << (*pscr2).get_cursor() << endl; 等價於 cout << Screen().get_cursor() << endl;
NoName noname(scr);
cout << noname->get_cursor() << endl; // 該行與下一行等價
cout << ((noname.operator ->()).operator ->())->get_cursor() << endl; // 返回類型是類類型的其他對象(或該對象的引用),遞歸調用->操作符
}
如果將ScreenPtr類的operator->成員函數返回類型改成Screen對象,則由於Screen類沒有重載operator->操作符,所有->只能作爲成員函數調用,而不能遞歸調用。
Screen test = pscr2.operator->(); // 最末一級只能返回指針