wordpress建设企业网站,雅布设计作品,做小程序要有网站吗,开发网站公司排行当运算符被用于类类型的对象时#xff0c;允许我们为其指定新的含义#xff1b;同时#xff0c;也能自定义类类型之间的转换规则。和内置类型的转换一样#xff0c;类类型转换隐式地将一种类型的对象转换成另一种我们所需类型的对象。
当运算符作用于类类型的运算对象时允许我们为其指定新的含义同时也能自定义类类型之间的转换规则。和内置类型的转换一样类类型转换隐式地将一种类型的对象转换成另一种我们所需类型的对象。
当运算符作用于类类型的运算对象时可以通过运算符重载重新定义该运算符的含义。
基本概念
重载的运算符是具有特殊名字的函数它们的名字由关键字operator 和其后要定义的运算符号共同组成。和其他函数一样重载的运算符也包含返回类型、参数列表以及函数体。
重载运算符函数的参数数量与该运算符作用的运算对象数量一样多。除了重载的函数调用运算符 operator()之外其他重载运算符不能含有默认实参。
当一个重载的运算符是成员函数时this 绑定到左侧运算对象。成员运算符函数的显式参数数量比运算对象的数量少一个。 通常情况下不应该重载逗号、取地址、逻辑与和逻辑或运算符。
调用重载运算符的两种方式 1.直接使用运算符。如 data1data2data1data2。 是非成员函数 是类的成员函数两种都可以直接使用。 2.向调用普通函数一样调用运算符函数。如 operator(data1,data2)data1.operator(data2)。 注意运算符函数的函数名是 operator 加运算符本身。
使用与内置类型一致的含义
如果类执行IO操作则定义移位运算符使其与内置类型的IO保持一致。如果类的某个操作是检查相等性则定义 operator如果类有了operator意味着它通常也应该有operator!。如果类包含一个内在的单序比较操作则定义 operator;如果类有了operator则它也应该含有其他关系操作。重载运算符的返回类型通常情况下应该与其内置版本的返回类型兼容逻辑运算符和关系运算符应该返回bool算术运算符应该返回一个类类型的值赋值运算符和复合赋值运算符则应该返回左侧运算对象的一个引用。
赋值运算符的行为与复合版本的类似赋值之后左侧运算对象和右侧运算对象的值相等并且运算符应该返回它左侧运算对象的一个引用。重载的赋值运算应该继承而非违背其内置版本的含义。
运算符选择作为成员或者非成员
赋值)、下标([])、调用()和成员访问箭头-运算符必须是成员。复合赋值运算符一般来说应该是成员但并非必须这一点与赋值运算符略有不同。改变对象状态的运算符或者与给定类型密切相关的运算符如递增、递减和解引用运算符通常应该是成员。具有对称性的运算符可能转换任意一端的运算对象例如算术、相等性、关系和位运算符等因此它们通常应该是普通的非成员函数。
输入和输出运算符
重载输出运算符
通常情况下输出运算符的第一个形参是一个非常量 ostream 对象的引用。 之所以 ostream 是非常量是因为向流写入内容会改变其状态而该形参是引用是因为我们无法直接复制一个ostream对象。 第二个形参一般来说是一个常量的引用该常量是我们想要打印的类类型。 第二个形参是引用的原因是我们希望避免复制实参而之所以该形参可以是常量是因为(通常情况下)打印对象不会改变对象的内容。 重载的 应该返回它的 ostream 形参。
通常输出运算符应该主要负责打印对象的内容而非控制格式输出运算符不应该打印换行符。 与iostream 标准库兼容的输入输出运算符必须是普通的非成员函数而不能是类的成员函数。但是应该声明为类的友元。
重载输出运算符
通常情况下输入运算符的第一个形参是运算符将要读取的流的引用第二个形参是将要读入到的非常量)对象的引用。该运算符通常会返回某个给定流的引用。 第二个形参之所以必须是个非常量是因为输入运算符本身的目的就是将数据读入到这个对象中。
输入运算符必须处理输入可能失败的情况而输出运算符不需要。 当流含有错误类型的数据时读取操作可能失败。当读取操作到达文件末尾或者遇到输入流的其他错误时也会失败。if(is)//检查输入是否成功item. revenue item.units_sold * price;
elseitem Sales_data();//输入失败:对象被赋予默认的状态如果在发生错误前对象已经有一部分被改变则适时地将对象置为合法状态异常重要。
算术和关系运算符
通常把算术和关系运算符定义成非成员函数以允许对左侧或右侧的运算对象进行转换 因为这些运算符一般不需要改变运算对象的状态所以形参都是常量的引用。
如果类同时定义了算术运算符和相关的复合赋值运算符则通常情况下应该使用复合赋值来实现算术运算符。
相等运算符
相等运算符来检验两个对象是否相等。
设计准则 1.将函数定义为 operator 而不是一个普通的命名函数 2.能判断一组给定对象中是否含有重复数据 3.具有传递性 4.如果定义了 operator那么也应该定义 operator1! 。
关系运算符
定义了相等运算符的类也常常但不总是包含关系运算符。特别是关联容器和一些算法要用到小于运算符所以定义operator。
设计准则 1.定义顺序关系令其与关联容器中对关键字的要求一致 2.如果类同时含有 运算符则定义关系要与 一致。
赋值运算符
类可以定义除了拷贝赋值和移动赋值运算符以外的其他运算符使用别的类型作为右侧运算对象。 可以重载赋值运算符。不论形参的类型是什么,赋值运算符都必须定义为成员函数。
赋值运算符必定义为类的成员复合赋值运算符通常情况下也应该这样做但复合赋值运算符不非得是类的成员。这两类运算符都应该返回左侧对象的引用。
下标运算符
表示容器的类通常可以通过元素在容器中的位置访问元素这些类一般会定义下标运算符operator[]。 下标运算符必须是成员函数。
下标运算符通常以所访问元素的引用作为返回值这样下标可以出现在赋值运算符的任意一端。
如果一个类包含下标运算符则它通常会定义两个版本一个返回普通引用另一个是类的常量成员并且返回常量引用。
递增和递减运算符
C 并不要求递增和递减运算符必须是类的成员但是因为它们改变的正好是所操作对象的状态所以建议将其设定为成员函数。
对于内置类型递增和递减运算符应该同时定义前置和后置版本。 前置版本返回递增或递减后的引用后置版本返回修改前的副本。
class StrBlobPtri{
public://递增和递减运算符StrBlobPtr operator(); //前置运算符StrBlobPtr operator--();//其他成员和之前的版本一致StrBlobPtr operator(int) ; //后置运算符StrBlobPtr operator--(int) ;//其他成员和之前的版本一致
};成员访问运算符
迭代器类和智能指针类通常会用到运算符* 和箭头运算符 - 箭头运算符必须是类的成员箭头运算符一般通过调用解引用运算符来实现。 解引用运算符通常也是类的成员但不必须的。
重载的箭头运算符必须返回类的指针或者自定义了箭头运算符的某个类的对象。
函数调用运算符
类重载函数调用运算符就可以像使用函数一样使用该类的对象。
函数调用运算符必须是成员函数。一个类可以定义多个不同版本的调用运算符相互之间应该在参数数量或类型上有所区别。
struct absInt{int operator()(int val)const {return val 0 ? -val : val;}int i-42;absInt absObj;//含有函数调用运算符的对象int ui absObj(i);//将i传递给abs0bj .operator()
}含有状态的函数对象类 和其他类一样函数对象类除了operator()之外也可以包含其他成员。函数对象类通常含有一些数据成员这些成员被用于定制调用运算符中的操作。
class PrintString {
public:PrintString(ostream o cout,char c):os(o), sep(c){}void operator()(const string s)const{ oss sep; }
private:ostream os;//用于写入的目的流char sep;//用于将不同输出隔开的字符
};lambda 是函数对象
编写一个lambda后编译器将该表达式翻译成一个未命名类的未命名对象。在lambda表达式产生的类中含有一个重载的函数调用运算符
//根据单词的长度对其进行排序对于长度相同的单词按照字母表顺序排序
stable_sort(words.begin(), words.end(),[](const string a, const string b){return a.size() b.size();});//其行为类似下面类的一个未命名对象
class ShorterString {
public:bool operator() (const string s1,const string s2) const{return sl.sizeo s2.size();}
};默认情况下 lambda不能改变它捕获的变量。因此在默认情况下由 lambda产生的类当中的函数调用运算符是一个const成员函数。如果lambda被声明为可变的则调用运算符就不是const的了。
当 lambda 通过引用捕获变量时由程序确保 lambda 执行时所引用的对象确实存在。因此编译器可以直接使用该引用而无须再 lambda 产生的类中将其存储为数据成员当 lambda 通过值捕获变量时产生的类必须为每个值捕获的变量建立对应的数据成员同时创建构造函数令其使用捕获的变量的值来初始化数据成员。
标准库定义的函数对象
标准库定义了一组表示算术运算符、关系运算符和逻辑运算符的类每个类分别定义了一个执行命名操作的调用运算符。这些定义在头文件 functional 中。 函数对象其实是一个函数对象类表示运算符的函数对象类常用来替换算法中的默认运算符。 标准库规定其函数对象对于指针同样适用。
可调用对象与 function
几种可调用的对象函数、函数指针、lambda表达式、bind创建的对象以及重载了函数调用运算符的类。
和其他对象一样可调用的对象也有类型两个不同类型的可调用对象可能共享同一种调用形式 调用形式指明了调用返回的类型以及传递给调用的实参类型。一种调用形式对应一个函数类型。
int (int, int)
//是一个函数类型它接受两个int、返回一个int。不同类型可能具有相同的调用形式
//普通函数
int add(int i, int j) { return i j;}
// lambda其产生一个未命名的函数对象类
auto mod [](int i, int j){return i %j;};
//函数对象类
struct divide{int operator()(int denominator, int divisor){return denominator / divisor;}
};三个可调用对象具有相同的调用形式 int(int,int)但是他们三个不是同一类型。
标准库 function 类型 不能直接将重载函数的名字存入 function 类型的对象中但是可以存储指向确定重载版本的函数指针。
functionint(int, int) f1 add; //add 是个函数指针
funcitonint(int, int) f2 divide(); //divide() 返回一个函数对象的对象。
functionint (int,int) f3 [](int i, int j)// lambda{return i*j;};cout f1(4,2) endl;//打印6
cout f2(4,2)endl;//打印2
cout f3(4,2)endl;//打印8不能直接将重载函数的名字存入 function类型的对象中会产生二义性问题
int add(int i, int j){return ij;}
Sales_data add(const Sales_data,const Sales_data);
mapstring, functionint (int, int) binops;
binops.insert( {,add} );//错误:哪个add?解决二义性问题1.存储函数指针而不是函数的名字; 2.使用 lambda 指定函数版本。
//1.存储函数指针
int(*fp)(int,int) add;//指针所指的add是接受两个int的版本
binops.insert ({fp) );//正确:fp指向一个正确的add版本//2.lambda
binops.insert({[](int a,int b){return add (a b);}});重载、类型转换与运算符
转换构造函数和类型转换运算符共同定义了类类型转换这样的转换有时也称为用户定义的类型转换。
类型转换运算符
类型转换运算符是类的一种特殊成员函数负责将一个类类型转换成其他类型。
operator type() const;类类型转换运算符可以面向能作为函数的返回类型的任意类型除了void 进行定义。 因此不能转换成数组或者函数类型但允许转换成指针包括数组指针以及函数指针或者引用类型。
类型转换运算符既没有显式的返回类型也没有形参而且必须定义成类的成员函数。类型转换运算符通常不应该改变待转换对象的内容因此类型转换运算符一般被定义成const成员。
class SmallInt{
public:SrmallInt (int i0) : val (i){if(i0 || i 255)throw std: :out_of_range (Bad SmallInt value);}operator int() const {return val;}
private:std::size_t val;
};//SmallInt 类既定义了向类类型的转换也定义了从类类型向其他类型的转换。其中,构造函数将算术类型的值转换成SmallInt对象而类型转换运算符将SmallInt对象转换成int:
SmallInt si;
si 4;//首先将4隐式地转换成 SmallInt然后调用 SmallInt::operator
si 3;//首先将si隐式地转换成 int然后执行整数的加法显式的类型转换运算符
class SmallInt {
public://编译器不会自动执行这一类型转换explicit operator into const{return val;}//其他成员与之前的版本一致
};//和显式的构造函数一样编译器通常也不会将一个显式的类型转换运算符用于隐式类型转换:
SmallInt si3;//正确:SmallInt的构造函数不是显式的
si 3;//错误:此处需要隐式的类型转换但类的运算符是显式的
static_castint(si) 3;//正确:显式地请求类型转当类型转换运算符是显式的时也能执行类型转换不过必须通过显式的强制类型转换才可以。
转换为 bool向 bool 类型的转换一般都用于条件部分因此 operator bool() 一般定义成 explicit 的。
避免有二义性的类型转换
如果类中包含一个或多个类型转换则必须确保在类类型和目标类型之间只存在唯一一种转换方式。否则代码将很可能会具有二义性。
有两种情况可能产生多重转换路径 1.两个类提供相同的类型转换。例如A 类定义了一个接受 B 类对象的转换构造函数同时 B 类定义了一个转换目标是 A 类的类型转换运算符 2.定义了多个转换规则。
注意除了显式地向bool类型的转换之外应该尽量避免定义类型转换函数并尽可能地限制那些“显然正确”的非显式构造函数。 1.不要令两个类执行相同的类型转换 2.避免转换目标是内置算术类型的类型转换。定义了一个转换算术类型的类型转换时不要再定义接受算术类型的重载运算符也不要定义转换到多种算术类型的类型转换。
函数匹配与重载运算符
重载的运算符也是重载的函数。 调用一个命名的函数时具有该名字的成员函数和非成员函数不会彼此重载。因为用来调用命名函数的语法形式对于成员函数和非成员函数来说是不相同的。
a.operatorsym(b); // a有一个 operatorsym成员函数
operatorsym(a, b);// operatorsym是一个普通函数表达式中运算符的候选函数集既应该包括成员函数也应该包括非成员函数。
如果对同一个类既提供了转换目标是算术类型的类型转换也提供了重载的运算符,则将会遇到重载运算符与内置运算符的二义性问题。
SmallInt sl,s2;
Smal1Int s3 s1 s2;//使用重载的operator
int i s3 0;//二义性错误重要术语
调用形式表示一个可调用对象的接口。在调用形式中包括返回类型以及一个实参类型列表该列表在一对圆括号内实参类型之间以逗号分隔。
类类型转换包括由构造函数定义的从其他类型到类类型的转换以及由类型转换运算符定义的从类类型到其他类型的转换。只接受单独一个实参的非显式构造函数定义了从实参类型到类类型的转换而类型转换运算符则定义了从类类型到某个指定类型的转换。
类型转换运算符是类的成员函数定义了从类类型到其他类型的转换。类型转换运算符必须是它要转换的类的成员并且通常被定义为常量成员。这类运算符既没有返回类型也不接受参数。它们返回一个可变为转换运算符类型的值也就是说operator int返回一个intoperator string返回一个 string,依此类推。
重载的运算符重定义了某种内置运算符的含义的函数。重载的运算符函数含有关键字operator之后是要定义的符号。重载的运算符必须含有至少一个类类型的运算对象。重载运算符的优先级、结合律、运算对象数量都与其内置版本一致。 文章转载自: http://www.morning.lzqdl.cn.gov.cn.lzqdl.cn http://www.morning.mjpgl.cn.gov.cn.mjpgl.cn http://www.morning.knngw.cn.gov.cn.knngw.cn http://www.morning.jtybl.cn.gov.cn.jtybl.cn http://www.morning.zcqgf.cn.gov.cn.zcqgf.cn http://www.morning.qcbhb.cn.gov.cn.qcbhb.cn http://www.morning.nbybb.cn.gov.cn.nbybb.cn http://www.morning.dydqh.cn.gov.cn.dydqh.cn http://www.morning.xnzmc.cn.gov.cn.xnzmc.cn http://www.morning.mczjq.cn.gov.cn.mczjq.cn http://www.morning.lrybz.cn.gov.cn.lrybz.cn http://www.morning.dphmj.cn.gov.cn.dphmj.cn http://www.morning.hwzzq.cn.gov.cn.hwzzq.cn http://www.morning.jpbpc.cn.gov.cn.jpbpc.cn http://www.morning.bnrff.cn.gov.cn.bnrff.cn http://www.morning.wqmpd.cn.gov.cn.wqmpd.cn http://www.morning.bqxxq.cn.gov.cn.bqxxq.cn http://www.morning.tmzlt.cn.gov.cn.tmzlt.cn http://www.morning.ltkms.cn.gov.cn.ltkms.cn http://www.morning.jopebe.cn.gov.cn.jopebe.cn http://www.morning.fmtfj.cn.gov.cn.fmtfj.cn http://www.morning.rfwkn.cn.gov.cn.rfwkn.cn http://www.morning.jkpnm.cn.gov.cn.jkpnm.cn http://www.morning.mwnch.cn.gov.cn.mwnch.cn http://www.morning.prxqd.cn.gov.cn.prxqd.cn http://www.morning.tklqs.cn.gov.cn.tklqs.cn http://www.morning.mgbcf.cn.gov.cn.mgbcf.cn http://www.morning.lyhrg.cn.gov.cn.lyhrg.cn http://www.morning.ypdhl.cn.gov.cn.ypdhl.cn http://www.morning.rnnq.cn.gov.cn.rnnq.cn http://www.morning.mgskc.cn.gov.cn.mgskc.cn http://www.morning.jrsgs.cn.gov.cn.jrsgs.cn http://www.morning.dmtld.cn.gov.cn.dmtld.cn http://www.morning.pszw.cn.gov.cn.pszw.cn http://www.morning.qpqwd.cn.gov.cn.qpqwd.cn http://www.morning.lqynj.cn.gov.cn.lqynj.cn http://www.morning.byzpl.cn.gov.cn.byzpl.cn http://www.morning.nqpy.cn.gov.cn.nqpy.cn http://www.morning.kgmkl.cn.gov.cn.kgmkl.cn http://www.morning.xysdy.cn.gov.cn.xysdy.cn http://www.morning.krjrb.cn.gov.cn.krjrb.cn http://www.morning.dmrjx.cn.gov.cn.dmrjx.cn http://www.morning.hcrxn.cn.gov.cn.hcrxn.cn http://www.morning.ddzqx.cn.gov.cn.ddzqx.cn http://www.morning.lgsqy.cn.gov.cn.lgsqy.cn http://www.morning.zlnmm.cn.gov.cn.zlnmm.cn http://www.morning.tqgx.cn.gov.cn.tqgx.cn http://www.morning.sthp.cn.gov.cn.sthp.cn http://www.morning.qjghx.cn.gov.cn.qjghx.cn http://www.morning.uycvv.cn.gov.cn.uycvv.cn http://www.morning.tlyms.cn.gov.cn.tlyms.cn http://www.morning.hgsylxs.com.gov.cn.hgsylxs.com http://www.morning.qllcm.cn.gov.cn.qllcm.cn http://www.morning.ghphp.cn.gov.cn.ghphp.cn http://www.morning.jwncx.cn.gov.cn.jwncx.cn http://www.morning.ygkk.cn.gov.cn.ygkk.cn http://www.morning.qwmsq.cn.gov.cn.qwmsq.cn http://www.morning.dbnpz.cn.gov.cn.dbnpz.cn http://www.morning.rrwgh.cn.gov.cn.rrwgh.cn http://www.morning.yjfzk.cn.gov.cn.yjfzk.cn http://www.morning.ghxzd.cn.gov.cn.ghxzd.cn http://www.morning.qlrtd.cn.gov.cn.qlrtd.cn http://www.morning.rmmz.cn.gov.cn.rmmz.cn http://www.morning.rqxch.cn.gov.cn.rqxch.cn http://www.morning.thlzt.cn.gov.cn.thlzt.cn http://www.morning.gmgnp.cn.gov.cn.gmgnp.cn http://www.morning.wfbs.cn.gov.cn.wfbs.cn http://www.morning.trlhc.cn.gov.cn.trlhc.cn http://www.morning.ljxxl.cn.gov.cn.ljxxl.cn http://www.morning.qnbgh.cn.gov.cn.qnbgh.cn http://www.morning.qckwj.cn.gov.cn.qckwj.cn http://www.morning.xqcbz.cn.gov.cn.xqcbz.cn http://www.morning.xq3nk42mvv.cn.gov.cn.xq3nk42mvv.cn http://www.morning.bphqd.cn.gov.cn.bphqd.cn http://www.morning.jbtzx.cn.gov.cn.jbtzx.cn http://www.morning.wpjst.cn.gov.cn.wpjst.cn http://www.morning.gryzk.cn.gov.cn.gryzk.cn http://www.morning.xkjrs.cn.gov.cn.xkjrs.cn http://www.morning.cwwbm.cn.gov.cn.cwwbm.cn http://www.morning.gjtdp.cn.gov.cn.gjtdp.cn