[转] 比较全面的 C++ 操作符重载 (operator)

标签:
c操作符operator重载it |
分类: 转 |
http://pic002.cnblogs.com/images/2012/445789/2012100101085035.jpg比较全面的 C++ 操作符重载 (operator)" />
http://pic002.cnblogs.com/images/2012/445789/2012100101090656.jpg比较全面的
重载不能改变操作符的优先级
如果一个内建操作符是一元的,那么所有对它的重载仍是一元的。如果是二元的重载后也是二元的
头文件Complex.h:
#include
using namespace
std;
class Complex {
public:
private:
};
Complex::Complex(){
}
Complex::Complex(double re)
{
};
Complex::Complex(double
re,double im) {
}
void Complex::write() const
{
};
Complex Complex::operator +
(const Complex &u) const {
}
Complex Complex::operator -
(const Complex &u) const {
}
Complex Complex::operator*
(const Complex &u) const {
}
Complex Complex::operator /
(const Complex &u) const {
}
测试文件:Complex.cpp和测试结果:
http://pic002.cnblogs.com/images/2012/445789/2012100112114123.jpg比较全面的
一个被重载的操作符,就是一个用户自定义的函数,只不过它可以享受操作符语法所带来的便利
除了内存管理操作符new、new[]、delete、delete[]之外,一个以顶层函数形式被重载的操作符必须在它的参数列表中包含一个类的对象
下标操作符[]、赋值操作符=、函数调用操作符()和指针操作符->必须以类成员函数的形式进行重载(这样可以保证第一个操作数是类的对象,不然9[x]、6.32=x,不被接受)
操作符(如%)要么以成员函数被重载,要么以顶层函数被重载。对于后者将至少带一个对象参数,这是因为操作符以顶层函数实现时,如果连一个参数都没有,那么对如下表达式
顶层函数重载操作符,类名和域解析符都没有了,因为它不是一个类成员函数
被重载的操作符,要么是一个类成员函数,要么在它的参数列表中包含一个类成员!!
下标操作符[]和函数调用操作符()只能以成员函数的形式被重载,不能成为顶层函数!!
eg:
http://pic002.cnblogs.com/images/2012/445789/2012100112443250.jpg比较全面的
修正后:
http://pic002.cnblogs.com/images/2012/445789/2012100112463560.jpg比较全面的
在上面那种情况,如果想要第二个表达式成功的话,就需要定义一个顶层函数重载+了
有一点要明白,当定义顶层函数时,函数里面不能含有对象的私有成员操作,否则编译通不过,下面有三种方法可以解决:
1,将私有成员设计为public成员,但是这种方法违背了类的信息隐藏原则
2,在Complex中加入用于访问real和imag的公有成员函数,但是容易造成接口混淆
3,将操作符重载函数声明为类的friend,但是不符合面向对象原则,应少用,建议仅在操作符重载时使用
类的私有成员只能被该类的成员函数和该类的friend函数访问
类的保护成员只能被该类的或其派生类的成员函数和该类的friend函数访问
class C {
friend int f();
//...
};
该声明赋予f访问C的私有和保护成员的权力,因为f不是成员函数,该声明可以放在C中的private、protected或public的任意部分,不受访问控制符的影响、限制
程序员可对操作符>>进行重载,以支持用户自定义数据类型。>>的第一个操作数是系统类的对象(如cin是系统类istream的对象),而这些重载函数时以类成员函数的形式实现的。
如果在对用户自定义的类型重载>>时,就必须对系统类的源代码进行修改,而这显然是非常不明智的做法,因此只能将>>重载函数设计为顶层函数
输入流对象总是以引用方式传递,这是因为系统为了接受输入数据,需要更新输入流对象的某些信息
如果被重载>>的函数中和类的私有数据或者保护数据打交道,则需要将重载操作符声明为friend
拷贝构造函数和赋值操作符(=),都是用来拷贝一个类的对象给另一个相同类型的对象。
拷贝构造函数将一个对象拷贝到另一个新的对象(因为拷贝-构造);赋值操作符将一个对象拷贝到另一个已经存在的对象
如果类的作者没有提供拷贝构造函数,也没有重载赋值操作符,编译器将会给这个类提供一个拷贝构造函数和一个赋值操作符。编译器提供的拷贝构造函数和赋值操作符的运转机制是:将源对象中的每个数据成员拷贝到目标对象相应的数据成员中
http://pic002.cnblogs.com/images/2012/445789/2012100116422292.jpg比较全面的
看例子:
http://pic002.cnblogs.com/images/2012/445789/2012100117462648.jpg比较全面的
如果类的作者定义了指针成员,且该指针指向一块动态分配的存储空间,就应该为这个类设计拷贝构造函数,并重载赋值操作符
注意不要返回临时变量,重载里面错综复杂,小心一点
下标操作符[]必须要以成员函数的形式进行重载!
returntype & operator[] (paramtype);
};
或者:
class C
{
const returntypr & operator[] (paramtype) const;
};
例子:
头文件:test.h
http://pic002.cnblogs.com/images/2012/445789/2012100119403572.jpg比较全面的
测试文件和结果:
http://pic002.cnblogs.com/images/2012/445789/2012100119413259.jpg比较全面的
上面可以不提供const版本的重载,但是就不能处理非const的对象,所以,有时候要考虑这一点,加上const重载!
函数调用操作符()必须要以成员函数的形式重载。
class C {
returntype operator()(paramtypes);
};
看例子:
头文件inttwoarray.h
#include
#include
using namespace std;
class intTwoArray {
public:
private:
};
int &
intTwoArray::operator() (int i,int j) {
}
const int &
intTwoArray::operator() (int i,int j) const {
}
intTwoArray::intTwoArray(int s1,int s2) {
}
测试程序和结果:
http://pic002.cnblogs.com/images/2012/445789/2012100120321992.jpg比较全面的
自增,自减也可以重载,但是前置,后置一共四种,前后置通过一个int参数区分,但是这个参数没有什么实际用途,仅仅起到区分的作用
例子:
#include
#include
using namespace std;
/
class Entry;
class Dict;
ostream & operator<<(ostream &,const Entry
&);
ostream & operator<<(ostream &,const Dict
&);
class Entry {
public:
private:
};
void
Entry::operator=(const string &str) {
}
void
Entry::operator=(const char * str) {
}
ostream &
operator<<(ostream &out,const Entry &e) {
}
void Entry::add(const
string &w,const string &d) {
}
bool Entry::match(const
string &key) const {
}
enum {MaxEntries = 100};
class Dict {
public:
private:
};
ostream &
operator<<(ostream &out,const Dict &d) {
}
Entry
&Dict::operator[](const string &k)
{
}
Entry &
Dict::operator[](const char *k) {
}
void Dict::remove(const
string &w)
{
}
测试程序和结果:
http://pic002.cnblogs.com/images/2012/445789/2012100211192625.jpg比较全面的
内存管理操作符new、new[]、delete和delete[]既可以用成员函数也可以用顶层函数重载
嵌入式内存有限,应用程序经常需要直接管理内存
new操作符重载:
void * C::operator new(size_t size) {
//...
}
和
void *
}
返回值void *
new和new[]操作符重载函数的第一个参数必须是size_t类型,其数值等于被创建对象大小,其他参数是可选的
delete操作符重载:
void C::operator delete( void * objPtr) {
//...
}
和
void operator delete(void *objPtr) {
}
delete和delete[]操作符重载函数的第一个参数必须是void*类型,返回值必须是void,而其他参数则是可选的
看例子:
头文件frame.h:
#include
#include
using namespace std;
const
int
const int
class Frame {
public:
void delete(void
*);
private:
};
Frame * allFrames =
0;
unsigned char framePool[MaxFrames * sizeof(Frame)];
bool alloc[MaxFrames];
Frame::Frame(const string
&n,const void *d, unsigned bsize) {
}
void Frame::print() const
{
}
void * Frame::operator
new(size_t size) {