2)因为要访问指定类的私有成员,所以在该类中声明输出操作符为友员函数。
3)第一个形参必须为引用。因为I/O对象不可以复制。同理返回值必须为一个引用。
4)第一个形参不可以为const,因为写入到流会改变其值。
5)第二个为引用,这样可以避免复制。参数可以为const,可以接收const对象和非const对象;否则,如果为非const,则只能接收非coust对象。一般为const,毕竟只是输出而已,不改变对象。
1.2 输入操作符
1.2.1 示例
#include
#include <string>
using namespace std;class A
{friend ostream& operator<<(ostream& out, const A& a);friend istream& operator>>(istream& in, A& a);public:A(const string &s &#61; "", int v &#61; 0) : ss(s), val(v) {}private:int val;string ss;
};ostream& operator<<(ostream& out, const A& a)
{out <<"a.ss:" <" " <<"a.val:" << a.val;return out;
}
istream& operator>>(istream& in, A& a)
{in >> a.ss >> a.val;if(in){cout <<"Input right" << endl;}else{cout <<"in.fail:" <<in.fail() << endl;cout <<"input wrong!" << endl;}return in;
}int main()
{A a("hello", 23);cout < endl;A b;cin >> b;cout < endl;
}
结果
1.2.2 说明
1&#xff09;输入与输出操作符的重要区别&#xff1a;输入操作符必须处理错误和文件结束的可能性。
2&#xff09;输入如果有多个值的话&#xff0c;如果一个数错了&#xff0c;整个输入对象就错了&#xff08;False&#xff09;&#xff0c;从示例中可以看出&#xff0c;前边赋值正确的已经生效了&#xff0c;后边的用了默认值&#xff0c;可以这样设计&#xff1a;如果输入错误&#xff0c;将整个对象复位&#xff0c;恢复到最初的状态&#xff0c;例&#xff1a;
View Code
2 算术操作符和关系操作符
2.1 相等操作符
2.1.1 示例
#include
#include <string>
using namespace std;class A
{friend bool operator&#61;&#61;(const A& a, const A& b);friend bool operator!&#61;(const A& a, const A& b);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}private:string ss;int val;
};bool operator&#61;&#61;(const A& a, const A& b)
{return a.ss &#61;&#61; b.ss && a.val &#61;&#61; b.val;
}bool operator!&#61;(const A& a, const A& b)
{return !(a &#61;&#61; b);
}int main()
{A a("hello", 53);A b("hello", 54);A c("hello", 54);cout <<"a &#61;&#61; b?:" <<(a &#61;&#61; b) << endl;cout <<"a !&#61; b?:" <<(a !&#61; b) << endl;cout <<"b &#61;&#61; c?:" <<(b &#61;&#61; c) << endl;cout <<"b !&#61; c?:" <<(b !&#61; c) << endl;
}
结果
2.1.2说明
1&#xff09;定义了类的&#61;&#61;&#xff0c;对应的应该定义&#xff01;&#61;
2.2 关系操作符
2.2.1 示例
#include
#include <string>
using namespace std;class A
{friend bool operator<(const A& a, const A& b);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}private:string ss;int val;
};bool operator<(const A& a, const A& b)
{return (a.val < b.val);
}int main()
{A a("hello", 53);A b("he", 55);cout <<"a " <<(a endl;
}
结果
2.2.2 说明
1&#xff09;定义了相等操作符&#xff0c;一般也定义关系操作符
2&#xff09;关系操作符要根据具体的含义定义
2.3 赋值操作符
2.3.1 示例
#include
#include <string>
using namespace std;class A
{friend ostream& operator<<(ostream& out, const A& a);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}A& operator&#61;(const A& a);private:string ss;int val;
};ostream& operator<<(ostream &out, const A& a)
{out <<"a.ss:" <" " <<"a.val:" << a.val;
}A& A::operator&#61;(const A& a)
{if(this !&#61; &a){ss &#61; a.ss;val &#61; a.val;}return *this;
}int main()
{A a("hello", 53);A b("he", 55);cout < endl;b &#61; a;cout < endl;
}
2.3.2 说明
1&#xff09; 复制操作符完成对同类对象的赋值&#xff0c;参数一般为对类类型的const引用。
2&#xff09;如果没有&#xff0c;编译器会自动合成一个&#xff0c;类的赋值操作符一定为类的成员变量&#xff0c;以便编译器是否需要自己合成一个。
3&#xff09;返回值必须为*this的引用&#xff0c;这样就不需要创建和撤销结果的临时副本。同理的有复合赋值操作符&#xff0c;例如
View Code 结果
2.4 加法操作符
2.4.1 示例
#include
#include <string>
using namespace std;class A
{friend ostream& operator<<(ostream& out, const A& a);friend A operator&#43;(const A &a ,const A &b);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}A(const A&);A& operator&#43;&#61;(const A &);private:string ss;int val;
};A::A(const A& a)
{ss &#61; a.ss;val &#61; a.val;
}ostream& operator<<(ostream &out, const A& a)
{out <<"a.ss:" <" " <<"a.val:" << a.val;
}A operator&#43;(const A &a ,const A &b)
{A tmp(a);tmp &#43;&#61; b;return tmp;
}A& A::operator&#43;&#61;(const A& a)
{val &#43;&#61; a.val;return *this;
}int main()
{A a("hello", 53);A b("he", 55);a &#43;&#61; b;cout < endl;
}
2.4.2 说明
1&#xff09; 根据复合操作符&#xff08;如&#43;&#61;&#xff09;实现算术操作符&#xff08;如&#43;&#xff09;&#xff0c;比其他方式更有效
3 下标操作符
3.1.1 示例
#include
#include <string>
using namespace std;class A
{friend ostream& operator<<(ostream& out, const A& a);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}char& operator[](const size_t);const& char operator[](const size_t) const;private:string ss;int val;
};ostream& operator<<(ostream& out, const A& a)
{out <<"a.val:" <" " <<"a.ss:" << a.ss;return out;
}char& A::operator[](const size_t index)
{return ss[index];
}const char& A::operator[](const size_t index) const
{return ss[index];
}int main()
{A a("hello", 53);cout <2] << endl;
}
结果
e
3.1.2 说明
1&#xff09; 下标操作必须为函数成员&#xff0c;因为传递一个参数&#xff0c;还需要另一个指向自己的指针参数&#xff0c;正好函数成员的this可以胜任。
2&#xff09; 类定义下标时&#xff0c;一般定义两个版本&#xff1a;一个为非const成员&#xff0c;并返回非const引用&#xff1b; 另一个为const成员&#xff0c;并返回const引用。这样应用与const对象时&#xff0c;返回值应为const引用&#xff0c;不能用作赋值的目标。
4 自加、自减操作符
4.1 前置自加、自减操作符
4.1.1 示例
#include
#include <string>
using namespace std;class A
{friend ostream& operator<<(ostream& out, const A& a);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}A& operator&#43;&#43;();A& operator--();private:string ss;int val;
};ostream& operator<<(ostream& out, const A& a)
{out <<"a.val:" <" " <<"a.ss:" << a.ss;return out;
}A& A::operator&#43;&#43;()
{&#43;&#43;val;return *this;
}A& A::operator--()
{--val;return *this;
}int main()
{A a("hello", 53);cout < endl;&#43;&#43;a;cout < endl;&#43;&#43;a;cout < endl;--a;cout < endl;
}
结果
4.2 后置自加、自减操作符
4.2.1 示例
#include
#include <string>
using namespace std;class A
{friend ostream& operator<<(ostream& out, const A& a);public:A(string s &#61; "", int v &#61; 0) : ss(s), val(v) {}A& operator&#43;&#43;();A& operator--();A operator&#43;&#43;(int);A operator--(int);private:string ss;int val;
};ostream& operator<<(ostream& out, const A& a)
{out <<"a.val:" <" " <<"a.ss:" << a.ss;return out;
}A& A::operator&#43;&#43;()
{&#43;&#43;val;return *this;
}A& A::operator--()
{--val;return *this;
}
A A::operator&#43;&#43;(int)
{A tmp(*this);&#43;&#43;(*this);return tmp;
}A A::operator--(int)
{A tmp(*this);--(*this);return tmp;
}int main()
{A a("hello", 53);cout < endl;&#43;&#43;a;cout < endl;&#43;&#43;a;cout < endl;cout <<"hello" << endl;cout <<(a--) << endl;;cout < endl;
}
4.2.2 说明
1&#xff09;为了区分与前置自加、自减操作符的区别&#xff0c;后置需要接受一个而外的&#xff08;无用的&#xff09;的int型形参。使用后缀式操作符时&#xff0c;编译器提供0作为这个形参的实参&#xff0c;其唯一目的是为了区别前缀、后缀。
2&#xff09;a&#43;&#43;返回的是加之前的状态&#xff0c;因此&#xff0c;定义一个局部对象&#xff0c;保存&#xff08;*this&#xff09;&#xff0c;最后返回这个局部变量的备份&#xff08;注意不可以为引用&#xff0c;毕竟是局部的&#xff09;。
5. 成员访问操作符
5.1.1 示例
#include
#include <string>
using namespace std;
class B
{public:void print_B() { cout <<"hello !!" << endl; }
};
class U_Ptr
{friend class HasPtr;B* ip;size_t use;U_Ptr(B *p) : ip(p), use(1) {}~U_Ptr() { delete ip; }
};class HasPtr
{public:HasPtr(B *p, int i) : ptr(new U_Ptr(p)), val(i) {}HasPtr(const HasPtr &orig) : ptr(orig.ptr), val(orig.val) { &#43;&#43;ptr->use; }HasPtr& operator&#61;(const HasPtr &orig);~HasPtr() { if(--ptr->use &#61;&#61; 0) delete ptr; }B& operator*() { return *ptr->ip; }B* operator->() { return ptr->ip; }private:U_Ptr *ptr;int val;
};HasPtr& HasPtr::operator&#61;(const HasPtr &orig)
{if(this !&#61; &orig){ptr &#61; orig.ptr;val &#61; orig.val;&#43;&#43;(ptr->use);}return *this;
}int main()
{HasPtr hasptr1(new B, 23);HasPtr hasptr2(hasptr1);*hasptr1;hasptr1->print_B();
}
结果
hello!!
5.1.2 说明
1&#xff09; 箭头必须定义为成员函数&#xff0c; 解引用不要求定义为成员&#xff0c;但是可以作为成员。
2&#xff09; 解引用和箭头操作常用在实现智能指针的类中。
本文转自jihite博客园博客&#xff0c;原文链接&#xff1a;http://www.cnblogs.com/kaituorensheng/p/3505115.html&#xff0c;如需转载请自行联系原作者