operator[],识别读操作和写操作
body, table{font-family: 微软雅黑; font-size: 10pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}
#include<iostream>
#include<string.h>
using namespace std;
class String
{ //23种设计模式之代理模式
class charProxy;
public:
String():_pstr(new char[2])
{
cout<<"String()"<<endl;
initRefcount();
}
String(const char *);
String(const String&);
String& operator=(const String&);
~String()
{
cout<<"~String()"<<endl;
decreaseRefcount();
if(0==useCount())
{
delete []_pstr;
}
}
int useCount()
{
return _pstr[strlen(_pstr)+1];
}
charProxy operator[](int index); //区分写操作,这里要返回一个临时对象就不能是一个引用了
// char& operator[](int idx)const; //区分读操作,必须加const关键字,不然和前面函数构成重载
private:
char* _pstr;
void initRefcount()
{
_pstr[strlen(_pstr)+1] = 1;
}
void increaseRefcount()
{
++_pstr[strlen(_pstr)+1];
}
void decreaseRefcount()
{
--_pstr[strlen(_pstr)+1];
}
class charProxy
{
public: //这些函数一定要是公有
charProxy(String& str,int index):_str(str),_index(index)
{
cout<<"charProxy(String&,int)"<<endl;
}
char& operator=(char ch); //嵌套类里面,也不能返回对象引用;因为嵌套类对象都是临时的
operator char()
{ //类型转换函数,由Charproxy转向char
cout<<"operator char()"<<endl;
return _str._pstr[_index];
}
private:
String& _str;
int _index;
};
friend ostream& operator<<(ostream&,const String&);
friend istream& operator>>(istream&,String&);
};
#if 0
//operator[]()不能区分读操作还是写操作
char & String::operator[](int idx)const //不能区分读写操作,废弃
{
cout<<"operator [](int)const"<<endl;
return _pstr[idx];
}
#endif
String::String(const char* tmp)
{
cout<<"String(const char*)"<<endl;
_pstr = new char[strlen(tmp)+2];
strcpy(_pstr,tmp);
initRefcount(); //引用计数设置为1
}
String::String(const String& lhs)
{
cout<<"String(const String&)"<<endl;
_pstr = lhs._pstr;
increaseRefcount();
}
String& String::operator=(const String& lhs)
{
cout<<"String& operator=(const String&)"<<endl;
decreaseRefcount();
if(0==useCount())
{
delete []_pstr;
}
_pstr = lhs._pstr; // 浅拷贝
increaseRefcount();
return *this;
}
ostream& operator<<(ostream& os,const String& rhs)
{
cout<<"ostream& operator<<(ostream& os,const String&)"<<endl;
os<<rhs._pstr<<endl;
return os;
}
istream& operator>>(istream& is,String& s)
{
cout<<"istream& operator>>(istream&,String&)"<<endl;
is>>s._pstr;
return is;
}
|
String::charProxy String::operator[](int index)
{
cout<<"charProxy operator[](int)"<<endl;
return charProxy(*this,index); //返回临时嵌套类对象
}
char& String::charProxy::operator=(char ch)
{
cout<<"char& operator=(char)"<<endl;
if(_index>=0&&_index<strlen(_str._pstr))
{
if(1==_str.useCount()) //当对象没有共享内存时
{
_str._pstr[_index] = ch; //修改
return _str._pstr[_index];
}
else
{
_str.decreaseRefcount(); //有共享内存
char* _strtmp = new char[strlen(_str._pstr)+2];
strcpy(_strtmp,_str._pstr);
_str = _strtmp; //这里调用了构造函数和赋值构造函数,操作完之后调用析构函数
_str[_index] = ch; //这里再次调动[]重载函数,进行修改
_str.initRefcount();
return _str._pstr[_index];
}
}
}
int main()
{
String s1("hello,world");
String s2(s1);
cout<<"读操作:"<<s1[1]<<endl;
cout<<s1.useCount()<<endl;
cout<<"--------------------------"<<endl;
cout<<"写操作:"<<endl;
s1[1] = 'm';
cout<<"--------------------------"<<endl;
cout<<s1[1]<<endl;
cout<<s1.useCount()<<endl;
return 0;
}
//String(const char*)
//String(const String&)
//charProxy operator[](int)
//charProxy(String&,int)
//operator char()
//读操作:e
//2
//--------------------------
//写操作:
//charProxy operator[](int)
//charProxy(String&,int)
//char& operator=(char)
//String(const char*)
//String& operator=(const String&)
//~String()
//charProxy operator[](int)
//charProxy(String&,int)
//char& operator=(char)
//--------------------------
//charProxy operator[](int)
//charProxy(String&,int)
//operator char()
//m
//1
//~String()
//~String()
|
这里要识别[]操作只能借助嵌套类来底层实现,因为不可能在String类中重写=运算符;所以当遇到[]操作符的时候就转化成CharProxy的对象,必须传引用对其本身操作,在这个类中就可以重写=运算符来区分读和写,因为这里的=我们后面不会再做其他用处只是区分读写;所以这里分三步: 重写[]运算符 先转换为嵌套类对象 重写=,区分s[]和是s[]= 改: |
operator[],识别读操作和写操作的更多相关文章
- (MariaDB/MySQL)MyISAM存储引擎读、写操作的优先级
MariaDB/MySQL中使用表级锁的存储引擎(例如MyISAM.Aria(MariaDB对MyISAM引擎的改进,前身是MyISAM))在读(select).写操作(insert.delete.u ...
- flash多进程写操作
1 应用场景介绍 硬件条件:使用stm32 MCU 软件条件:协议栈应用 协议栈简单介绍如下: 类似于OSI七层模型,所涉及的协议栈包括应用层,网络层,链路层,物理层,如下图: 在 ...
- C#多线程:使用ReaderWriterLock类实现多用户读/单用户写同步
摘要:C#提供了System.Threading.ReaderWriterLock类以适应多用户读/单用户写的场景.该类可实现以下功能:如果资源未被写操作锁定,那么任何线程都可对该资源进行读操作锁定, ...
- 使用ReaderWriterLock类实现多用户读/单用户写同步
使用ReaderWriterLock类实现多用户读/单用户写同步[1] 2015-03-12 应用程序在访问资源时是进行读操作,写操作相对较少.为解决这一问题,C#提供了System.Threadin ...
- HDFS的工作原理(读和写操作)
工作原理: NameNode和DateNode,NameNode相当于一个管理者,它管理集群内的DataNode,当客户发送请求过来后,NameNode会 根据情况指定存储到哪些DataNode上,而 ...
- CI中获取读操作的结果集行数+获取写操作的影响行数
本质:读操作,用mysql_num_rows函数,写操作用mysql_affected_rows函数 mysql_num_rows() 返回结果集中行的数目.此命令仅对 SELECT 语句有效.要取得 ...
- 汇编指令-MRS(读)和MSR(写)指令操作CPSR寄存器和SPSR寄存器使用(1)
1.MSR和MRS指令介绍 MRS 指令: 对状态寄存器CPSR和SPSR进行读操作.通过读CPSR可以获得当前处理器的工作状态.读SPSR寄存器可以获得进入异常前的处理器状态(因为只有异常模式下有 ...
- python中文件的读和写操作
一.打开文件 data = open("yesterday",encoding="utf-8").read() # python默认的打字符编码是unicode ...
- 基于.net EF6 MVC5+WEB Api 的Web系统框架总结(4)-Excel文件读、写操作
Excel文件读.写可以使用Office自带的库(Microsoft.Office.Interop.Excel),前提是本机须安装office才能运行,且不同的office版本之间可能会有兼容问题.还 ...
随机推荐
- 论文笔记:CNN经典结构1(AlexNet,ZFNet,OverFeat,VGG,GoogleNet,ResNet)
前言 本文主要介绍2012-2015年的一些经典CNN结构,从AlexNet,ZFNet,OverFeat到VGG,GoogleNetv1-v4,ResNetv1-v2. 在论文笔记:CNN经典结构2 ...
- win7系统下查看端口的占用情况以及如何删除端口进程
经常在本地测试开发使用tomcat的时候容易报端口占用的情况,比如我要查看8080端口的使用情况 1.按如下操作,输入 cmd 回车 2.在doc窗口中输入命令 netstat -ano | f ...
- I.MX6中PC连接开发板问题
修改板端的文件 添加登录密码: passwd vi /etc/network/interrfaces 在auto eth0下增加auto eth1 如果采用固定ip方式可以在后面增加一段固定ip设置 ...
- Linux中find
Linux中find常见用法示例 ·find path -option [ -print ] [ -exec -ok command ] {} \; find命令的参数 ...
- ipythons 使用攻略
ipython是一个 python 的交互式 shell,比默认的 python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数. 安 ...
- Phred-scale quality scores的相关内容
phred-scale quality score起源于人类基因组计划,最初是用来评估碱基质量分数,后来,被广泛的推广到基因领域的其他内容. phred-scalequality score表示这件事 ...
- 20145322《Java程序设计》第十周学习总结
20145322<Java程序设计>第十周学习总结 教材学习内容总结 网络概述 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定的位置,或 ...
- openwrt下如何只编译linux内核
答:make target/linux/install V=s (此操作也会将最终镜像打包好,V=s会输出日志) 拓展 清空内核: make target/linux/clean V=s 解压内核: ...
- 从零开始玩转JMX(二)——Condition
Notification 一个MBean提供的管理接口允许代理对其管理资源进行控制和配置.然而,对管理复杂的分布式系统来说,这些接口知识提供了一部分功能.通常,管理应用程序需要对状态变化或者当特别情况 ...
- Animal_human_kp人脸与马脸迁移学习GitHub 论文实现
Interspecies Knowledge Transfer for Facial Keypoint Detection关键点检测 Github地址:Interspecies Knowledge ...