随感而发

杂七杂八

统计

留言簿(13)

阅读排行榜

评论排行榜

c++操作符重载

今天我学习的是C++操作符重载。C++的操作符重载给C++带来很大的方便和灵活性。可以重载里面大部分操作符。这样在调用的时候就会相对的自然和简单。废话少说,直接奉上源代码(有部分相关的资料的注释都已经写在源代码上了):
  1 //一位是学习代码,所以写的相对叫乱,如果是其他的就应该规范些
  2 #include<stdio.h>
  3 #include <stdlib.h>
  4 
  5 //总结:重载操作符可以写成成员函数和友员函数。成员函数是类内部的
  6 //函数,而友员函数是外部的函数,例如全局函数,甚至其他类里面的函数,我的习惯是
  7 //写成成员函数,因为我觉得这样感觉要好一点,而且在成员函数中参数还可以少一个。
  8 //哈哈,不过问题就是他不能重载左二元操作符(符号在他的左边),也就是操作符是在他的左边,所以在
  9 //重载一个整数和这个类相加的情况就只能写友员函数了。
 10 //重载操作符的参数个数一定要跟默认参数个数的一样,除了()这样的可以自己定义以外,
 11 //例如operator+();这是错误的,还有operator(int a, int b,int c);这也是错误的
 12 //我下面之所以只有一个,是因为他是成员函数。自己已经包括在里面了,而友员就必须两个都写。
 13 //重载的返回类型没有规定,C++也不是用返回来判断是否重载的,
 14 //他是根据函数名和参数列表来判断的。成员函数加const也是重载的一种,但是如果其他都一样只有
 15 //返回类型不一致,就认为是错误的重载。例如:
 16 //int operator+(int nAdd) const;和 
 17 //CBaseOperator operator+(const CBaseOperator& cAdd) const;就会认为是错误的重载
 18 //而int operator+(int nAdd) const;和int operator+(int nAdd);就是正确的,他们是两个不同的函数
 19 //在调用上,在未指明为const的类调用时,使用的是非const的函数。如果没有非const的函数,
 20 //他才会调用const的函数。而如果const的类去调用非const的函数,会直接报错。所以
 21 //在写代码时,可以考虑是不是可能会修改成员,如果希望是不修改的,那么请用const,这样强制性的
 22 //会提高你的编码能力的。(扯远了,呵呵。)
 23 //都说友员是一个强大的东东,可以访问内部的private函数和变量,但是,如果把拷贝构造函数和
 24 //=重载为私有的话,他是不能访问的。。哈哈。设计语言的人真厉害。。
 25 
 26 //百度百科找的资料:
 27 //什么时候定义类成员操作符重载,什么时候定义非类成员操作符重载?
 28 //答:(1)如果一个重载操作符是类成员,那么只有当跟它一起使用的左操作数是该类对象时,
 29 //它才会被调用,如果该操作符的左操作数必须是其他类型,那么重载操作符必须是非类成员操作符重载。
 30 //(2)C++要求,赋值(=),下标([ ]),调用(())和成员访问箭头(->)操作符必须被指定为类成员操作符,否则错误。
 31 
 32 //http://www.examda.com/ncre2/cpp/fudao/20080312/092830274-2.html 网站的资料
 33 //不能重载的操作符号:
 34 //. .* :: ?: new delete sizeof typeid static_cast dynamic_cast const_cast reintERPret_cast
 35 //可以重载的操作符:
 36 //operator new operator delete operator new[] operator delete[] 
 37 // + - * / % ^ & | ~ ! = < > += -= *= /= %=  ^= &= |= << >> >>= <<= == !=
 38 // <= >= && || ++ -- , ->* -> () []
 39 //貌似这里可以重载new
 40 
 41 //重载简单的+-*/%等
 42 class CBaseOperator
 43 {
 44 
 45 public:
 46     int nData;        //测试的变量
 47 
 48 public:
 49     CBaseOperator(int nData = 0):nData(nData)
 50     {
 51         nData++;
 52         --nData;
 53     }
 54 
 55     
 56     CBaseOperator(const CBaseOperator& cBO)
 57     {
 58         nData = cBO.nData;
 59     }
 60     //重载=操作符,一般=操作符和拷贝构造函数是成对出现的。
 61     const CBaseOperator& operator=(const CBaseOperator& cBO)
 62     {
 63         nData = cBO.nData;
 64         return *this;
 65     }
 66 
 67 public:
 68 
 69     //重载+操作符,简单的二元操作符重载是最常见也是比较简单的。基本思路都是这样,注意如果
 70     //操作符出现在左边,则只能用友员了。这里了有几个返回类型是CBaseOperator,return
 71     //语句中却是两个int相加,这种情况是可以通过的,编译器会自动构建一个相应的对象返回,
 72     //前提是你的构造函数要有相应的参数,这里是int作为参数
 73     int operator+(int nAdd) const
 74     {
 75         return nData + nAdd;
 76     }
 77 
 78     int operator+(int nAdd)
 79     {
 80         return nData + nAdd;
 81     }
 82     
 83     friend int operator+(int nAdd,const CBaseOperator& cAdd)
 84     {
 85         return nAdd + cAdd.nData;
 86     }
 87     
 88     CBaseOperator operator+(const CBaseOperator& cAdd) const
 89     {
 90         return nData + cAdd.nData;
 91     }
 92 
 93     //重载减法什么的也是一样。就不写了。哈哈
 94 
 95     //比较操作符重载==,!=,>, >=, <, <=总结:这里都是配套的操作一般来说如果写一个
 96     //都会重载其他几个,特别是==,!=。当然也有例外。哈哈。。
 97     bool operator==(const CBaseOperator& cEqual) const
 98     {
 99         return nData == cEqual.nData;
100     }
101     bool operator == (int nEqual) const
102     {
103         return nData == nEqual;
104     }
105     friend bool operator ==(int nEqual, const CBaseOperator& cEqual)
106     {
107         return cEqual.nData == nEqual;
108     }
109     bool operator!=(const CBaseOperator& cEqual) const
110     {
111         return nData != cEqual.nData;
112     }
113 
114     //其他的也就不写了,基本一样。哈哈
115 
116     //重载++,--操作符,因为++,--有两种方式,一种是前增量(++XXX先改变自己,返回),
117     //一种是后增量(改变自己,返回改变前的状态)
118     //因为重载是判断参数的,为了能区别前增量和后增量,C++的设计者做了这样的考虑。
119     //就是重载后增量的时候在参数列表中加一个int类型参数,这样就避免的重载的重复了。
120     //在调用上,如果都重载,那么用int参数的是后增量++,没有参数的是前增量++,
121     //(注:我在这里说的是成员函数,当然友员的重载参数个数要多一个,以后的我可别说我无知啊。)
122     //如果都重载,那么前增量和后增量都会调用相应的函数,如果只重载了后增量,那么前增量会失败
123     //如果只重载了前增量,就会无论是前增量和后增量都会调用这个函数。所以一般他们也是成对
124     //出现的,除非你懒,只写前增量,可惜如果人家要调用后增量呢?结果会错的哦。哈哈。
125 
126     //重载后增量.
127     CBaseOperator operator++(int)
128     {
129         CBaseOperator cTemp = *this;
130         ++nData;
131         return cTemp;
132     }
133 
134     //重载前增量
135     CBaseOperator& operator++()
136     {
137         ++nData;
138         return *this;
139     }
140 
141     //重载--操作符是一样的,也不写了。
142 
143     //重载[],()等操作符号,同样[]的参数个数是确定的。
144     //我之说以把他们写一起,是因为我错误的以为[]的参数个数是可以自己定义。错了错了。
145     //知错能改是好的,对了,()的参数个数是可以自己定义的。这个就给我们很大的发挥空间了。
146     //都忘了[],() = 等操作符必须是成员函数,上面有写。不能用友员和静态成员函数
147 
148     //重载[]
149     int operator[](int nIndex) const
150     {
151         return nIndex;
152     }
153 
154     //重载()
155     int operator()(int a) const
156     {
157         return a;
158     }
159 
160     bool operator()(int a, int b) const
161     {
162         return a > b;
163     }
164 
165     CBaseOperator operator()(int a, int b, int c)
166     {
167         return CBaseOperator(a+b+c+*this);
168     }
169 
170     //重载*,->的操作符,*操作符就是相当于指针的*p;不过这里已经失去了原来的意义,他不是一个指针了。
171     //但如果是想通过他来得到一些东西,也是可以的,特别在迭代器中常用这种方法。->也是和*配对出现的。
172     //不过->操作符比较有意思,貌似和(*p).dddd真的差不多,所以返回的应该是一个结构的指针,我们这里
173     //就返回了本身,当然可以返回任何结构的指针的。(并不是只能返回本身)。
174 
175     //重载*,这里参数个数是固定的,多写一个就成了乘法的操作了。哈哈
176     int operator*() const
177     {
178         return nData;
179     }
180 
181     //重载->
182     CBaseOperator* operator->()
183     {
184         return this;
185     }
186 
187     //其他的例如&& || 这样的操作符还是不重载的好。利用其原有的本性
188 
189     //重载new delete,这里编译器做了一个限制,new必须返回void*类型, delete必须
190     //返回void类型。(上面说过函数重载是不检查返回类型的,和这里并没有冲突,他只是限定了返回
191     //类型,而不是只有返回类型不同的函数能重载,这个是编译器做的工作,一定上确保new能更好的工作吧)
192     //还有就是他们的参数个数都是可以自定义的。new 和 new[] 是两个不同的操作符,所以还是要分别重载一下。
193     //delete 和 delete[] 也是两个不同的操作符。这里只重载了一个。
194     void* operator new(size_t size)
195     {
196         
197         return  malloc(size);
198     }
199 
200     void* operator new[](size_t size)
201     {
202         return  malloc(size);
203     }
204 
205     void operator delete(void* P, unsigned int size)
206     {
207         size = 0;
208         free(P);
209     }
210 };
211 
212 int main()
213 {
214     const CBaseOperator cCo1(100);
215 
216     //判断+重载符
217     int nSum = cCo1 + 50;
218     printf("%d\n", nSum);
219     nSum = 50 + cCo1;
220     printf("%d\n", nSum);
221 
222     //这里顺便检测一下拷贝构造函数
223     CBaseOperator co2(20);
224     CBaseOperator co3 = co2 + cCo1;
225     nSum = co3.nData;
226     printf("%d\n", nSum);
227 
228     nSum = co3 + 60;
229     printf("%d\n", nSum);
230 
231     //检测+,和=操作符
232     co3 = 10 + cCo1 + co2 + 20;
233     nSum = co3.nData;
234     printf("%d\n", nSum);
235 
236     //查看比较操作符
237     if (cCo1 == cCo1 && cCo1 == 100 && 100 == cCo1)
238     {
239         printf("True\n");
240     }
241     co3 = co2;
242     if (!(co3 != co2))
243     {
244         printf("True\n");
245     }
246 
247     //增量操作符,cCo1是不能做这个操作的,因为他是常量
248     nSum = co2.nData;
249     printf("%d\n", nSum);
250     nSum = (co2++).nData;
251     printf("%d\n", nSum);
252     nSum = (++co2).nData;
253     printf("%d\n", nSum);
254 
255     //测试[],
256     nSum = cCo1[45];
257     printf("%d\n", nSum);
258 
259     //测试()
260     nSum = cCo1(50);
261     printf("%d\n", nSum);
262     
263     if (cCo1(4523))
264     {
265         printf("True\n");
266     }
267 
268     co2 = co3(10,20,30);
269     nSum = co2.nData;
270     printf("%d\n", nSum);
271 
272     //测试*,这里co2并不是指针哦。只是重载了*的操作符
273     nSum = *co2;
274     printf("%d\n", nSum);
275 
276     //测试->,这里也一样。
277     nSum = co2->nData;
278     printf("%d\n", nSum);
279 
280     //测试new new[] delete,
281     //这里没有测试输出。单步就知道了。
282     CBaseOperator* pCb1 = new CBaseOperator();
283     CBaseOperator* pCb2 = new CBaseOperator[10];
284     delete pCb1;
285     delete pCb2;
286 
287     system("pause");
288     return 0;
289 }
290 

posted on 2009-04-01 13:10 shongbee2 阅读(19680) 评论(8)  编辑 收藏 引用 所属分类: c/c++

评论

# re: c++操作符重载 2009-04-01 22:52 Herb

如果理解了,可能就几句就说清了,如果不理解,可能就是长篇大论。  回复  更多评论   

# re: c++操作符重载 2009-04-01 23:59 shongbee2

@Herb
貌似我没有懂大侠的话!您的意思是我写的啰嗦了是吧!呵呵,谢谢啦。
我语文很烂,不过我会努力改正的。呵呵。耽误了您的时间,抱歉哈。  回复  更多评论   

# re: c++操作符重载 2009-04-15 16:04 yatou

哈~看完了,学到不少东西了~谢谢啦~  回复  更多评论   

# re: c++操作符重载 2009-04-17 01:16 shongbee2

@yatou
呵呵,能给你带来帮助是对我最大的奖赏。加油。  回复  更多评论   

# re: c++操作符重载 2009-05-14 12:08 tw

感谢你与大家分享  回复  更多评论   

# re: c++操作符重载 2010-03-11 09:48

很好,呵呵  回复  更多评论   

# re: c++操作符重载 2012-03-20 16:10 wenxin

收益了  回复  更多评论   

# re: c++操作符重载 2012-04-19 22:45 张永昌

其实,c++标准库有内建的工具帮你生成其它的所有大小的操作符,只需要重载其中的两个比较操作符就可以了,根据你的语义可以采用,没必要写这么多的代码。  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理