码迷,mamicode.com
首页 > 编程语言 > 详细

c++运算符重载

时间:2015-05-23 00:02:00      阅读:382      评论:0      收藏:0      [点我收藏+]

标签:

//全局函数和静态函数的转换

#include <iostream>

using namespace std;

?

class Test

{

public:

????Test(int a = 0, int b = 0)

????{

????????this->a = a;

????????this->b = b;

????}

public:

????int a;

????int b;

public:

????//全局函数

????Test T_add(Test &t1, Test &t2)

????{

????????Test t3;

????????t3.a = t1.a + t2.a;

????????t3.b = t1.b + t2.b;

????????return t3;

????}

????Test& add(Test &t2) //面向对象编程

????{

????????a = a + t2.a;

????????b = b + t2.b;

????????return *this;

????}

};

//全局函数

Test T_add(Test &t1, Test &t2)

{

????Test t3;

????t3.a = t1.a + t2.a;

????t3.b = t1.b + t2.b;

????return t3;

}

?

Test T_add01(Test *pthis, Test &t1, Test &t2)

{

????Test t3;

????t3.a = t1.a + t2.a;

????t3.b = t1.b + t2.b;

????return t3;

}

//从成员函数转换为全局函数,只需要加一个this指针(一个指向本类的指针)

//从全局函数转换为类的成员函数,只需要减去一个左操作数

void Demo01()

{

????Test t1(2, 3), t2(3, 4);

????Test t3 = T_add(t1, t2);

????t3 = t1.T_add(t1, t2);

}

void main()

{

????system("pause");

}

从成员函数转换为全局函数,只需要加一个this指针(一个指向本类的指针),而从从全局函数转换为类的成员函数,只需要减去一个左操作数即可,正如上面的代码所示。

运算符重载练习

#include <iostream>

using namespace std;

?

class Complex

{

public:

????int a;

????int b;

public:

????Complex(int a = 0, int b = 0)

????{

????????this->a = a;

????????this->b = b;

????}

????void print()

????{

????????printf("%d+%di\n", a, b);

????}

?

};

Complex add(Complex &lop, Complex &rop)

{

????Complex result;

????result.a = lop.a + rop.a;

????result.b = lop.b + rop.b;

????return result;

}

?

Complex operator+(Complex &lop, Complex &rop)//重载

{

????Complex result;

????result.a = lop.a + rop.a;

????result.b = lop.b + rop.b;

????return result;

}

void Demo01()

{

????Complex c1(1, 2), c2(3, 4);

????//c1 = c1 + c2; //编译器压根不知道怎么加,但是编译器会给你提供一种机制,会让你实现自定义加操作

????Complex c3 = add(c1, c2); //直接调用函数add

}

void Demo02()

{

????Complex c1(1, 2), c2(3, 4);

????//操作符重载首先是通过函数实现的

????//+操作符有两个参数,左操作数和右操作数,特别留意左操作数

????Complex c3 = c1 + c2; //实现了重载

????//Complex c3 = operator+(c1, c2);//这样写也不会错

}

?

void main()

{

????Demo02();

????system("pause");

}

一般的类变量是设置成private属性的,因此我们一般都用友元函数实现运算符重载。

#include <iostream>

using namespace std;

?

class Complex

{

private:

????int a;

????int b;

public:

????Complex(int a = 0, int b = 0)

????{

????????this->a = a;

????????this->b = b;

????}

????//通过友元函数实现操作符重载

????friend Complex operator+(Complex &lop, Complex &rop);

????friend Complex &operator++(Complex &lop);

????friend Complex operator++(Complex &lop, int/*占位符*/);

????//通过类的成员函数实现减号操作

????Complex operator-(Complex &rop) //左操作数隐藏在this指针里面

????{

????????Complex res;

????????res.a = a - rop.a;

????????res.a = b - rop.b;

????????return res;

????}

????Complex &operator--()

????{

????????a--;

????????b--;

????????return *this;

????}

????Complex operator--(int) //后置--的成员函数实现

????{

????????Complex tmp = *this;

????????this->a--;

????????this->b--;

????????return tmp;

????}

????void print()

????{

????????printf("%d + %di\n", a, b);

????}

?

};

?

Complex operator++(Complex &lop, int/*占位符*/)

{

????Complex tmp = lop;

????lop.a++;

????lop.b++;

????return tmp;

}

//全局函数原型推导

Complex &operator++(Complex &lop)

{

????lop.a++;

????lop.b++;

????return lop;

}

Complex operator+(Complex &lop, Complex &rop)

{

????Complex result;

????result.a = lop.a + rop.a;

????result.b = lop.b + rop.b;

????return result;

}

void Demo01()

{

????Complex c1(1, 2), c2(3, 4);

????//c1 = c1 + c2; //编译器压根不知道怎么加,但是编译器会给你提供一种机制,会让你实现自定义加

????Complex c4 = c1 - c2;

????Complex c5 = c1.operator-(c2);

????//目标,通过类的成员函数完成操作符重载

????//1.要承认操作符操作是一个函数,要写函数原型

????//2.写出函数调用语言

????//3.完善函数原型

?

}

void Demo02()

{

????Complex c1(1, 2), c2(3, 4);

????//Complex c3 = operator+(c1, c2);

????//操作符重载首先是通过函数实现的

????//+操作符有两个参数,左操作数和右操作数,特别留意左操作数

????Complex c3 = c1 + c2;

?

}

?

void Demo03()

{

????Complex c1(1, 2), c2(3, 4);

????c1++;

????c1.print();

????--c2;

????c2++;

????//先使用c2的属性,然后让属性+++

????//operator++(c2, int/*占位符*/);//后置++

????c2.print();

????//成员函数实现后置--

}

?

void main()

{

????Demo03();

????system("pause");

}

使用友元函数和类的成员函数都可以实现操作符重载,正如同前面所提到的,成员函数由于已经包含了this指针,所以省略了一个操作数,其实两者差别不大。不过也存在差别,成员函数和友元函数重载操作符各有用处。规范的写法是,一般可以用成员函数实现的操作符重载就不用友元函数,所以使用友元函数重载的地方就很少了,一处场景如下下段代码所示。

关于前置++和后置++需要注意几点:

前置++的版本一般是这么写:foo& operator++() //前置++,前置返回引用

后置++一般这么写:foo operator++(int) //后置++,后置返回对象

前置返回引用,后置返回对象这是通用做法。

class foo

{

public:

????foo operator++() //后置++,后置返回对象

????{

????????a++;

????????return *this;

????}

????foo& operator++(int) //前置++,前置返回引用,int占位符,只是标记,将前置和后置区分开来

????{

????????a++;

????????return *this;

????}

public:

????foo(int a = 0)

????{

????????this->a = a;

????}

private:

????int a;

};

在实际中,我们一般不用友元函数重载运算符,一般都用成员函数,但是使用友元函数重载运算符也有用武之地,下面是规范的写法:

#include <iostream>

using namespace std;

?

class Complex

{

private:

????int a;

????int b;

public:

????Complex(int a = 0, int b = 0)

????{

????????this->a = a;

????????this->b = b;

????}

????//通过类的成员函数实现减号操作

????Complex operator-(Complex &rop) //左操作数隐藏在this指针里面

????{

????????Complex res;

????????res.a = a - rop.a;

????????res.a = b - rop.b;

????????return res;

????}

????Complex operator+(Complex &rop) //左操作数隐藏在this指针里面

????{

????????Complex res;

????????res.a = a + rop.a;

????????res.a = b + rop.b;

????????return res;

????}

????Complex &operator++()

????{

????????a++;

????????b++;

????????return *this;

????}

????Complex operator++(int) //后置--的成员函数实现

????{

????????Complex tmp = *this;

????????this->a++;

????????this->b++;

????????return tmp;

????}

????Complex &operator--()

????{

????????a--;

????????b--;

????????return *this;

????}

????Complex operator--(int) //后置--的成员函数实现

????{

????????Complex tmp = *this;

????????this->a--;

????????this->b--;

????????return tmp;

????}

????void print()

????{

????????printf("%d + %di\n", a, b);

????}

????friend ostream& operator<<(ostream &out, Complex &op); //这里才是friend函数的真正用武之地

protected:

private:

?

};

?

ostream& operator<<(ostream &out, Complex &op)

{

????out << op.a << " " << op.b << endl;

????return out;

}

void Demo01()

{

????Complex c1(1, 2), c2(3, 4);

????int a = 10;

????char *p = "abc";

????cout << p << endl;

????//没有办法在cout类里面添加函数operator<<只能通过全局函数实现

????cout << c1;

????cout << c1 << endl << "链式编程测试" << endl;

????//void operator<<(ostream &out, Complex &op);

????//operator<<(cout, &c1);

????//void << endl;

????//函数返回值当左值的时候,需要返回一个对象的引用

?

}

?

void main()

{

????Demo01();

????system("pause");

}

特别需要注意的地方是,如果ostream& operator<<(ostream &out, Complex &op)写成了void operator<<(ostream &out, Complex &op),虽然执行cout << c1;不会出错,但是执行cout << c1 << endl << "链式编程测试" << endl;会出错,这是因为operator=的返回值的缘故,cout << c1相当于执行operator<<(cout, c1),返回void,接下来执行void << endl,不错才怪。

同时,上面的ostream& operator<<(ostream &out, Complex &op)是友元函数运用的绝好时期,因为cout并没有在成员函数里实现operator<<(Complex &op),当然它也不可能实现,怎么办呢?恰好运用友元函数可以解决这个问题。

接下来是运算符重载的一个很好的例子:

/*Array.h*/

#ifndef _ARRAY_H_

#define _ARRAY_H_

#include <iostream>

class Array

{

private:

????int mLength;

????int* mSpace;

?

public:

????Array(int length);

????Array(const Array& obj);

????int length();

????void setData(int index, int value);

????int getData(int index);

????~Array();

public:

????int& operator[](int index);

????Array& operator=(Array &rop);

????bool operator==(Array &rop);

????bool operator!=(Array &rop);

};

?

?

//[] = == !=

//

?

?

#endif

?

/*Array.cpp*/

#include "iostream"

#include "Array.h"

using namespace std;

?

//区别 如果不加引用会构造一个匿名对象(临时对象)

//开销会非常大

Array::Array(int length)

{

????if (length < 0)

????{

????????length = 0;

????}

?

????mLength = length;

????mSpace = new int[mLength];

}

?

Array::Array(const Array& obj)

{

????mLength = obj.mLength;

?

????mSpace = new int[mLength];

?

????for (int i = 0; i<mLength; i++)

????{

????????mSpace[i] = obj.mSpace[i];

????}

}

?

int Array::length()

{

????return mLength;

}

?

void Array::setData(int index, int value)

{

????mSpace[index] = value;

}

?

int Array::getData(int index)

{

????return mSpace[index];

}

?

Array::~Array()

{

????mLength = -1;

????delete[] mSpace;

}

?

//需要当左值,返回引用

//返回引用是要注意生命周期

/************************************************************************/

/*

Complex &operator-(operator &rop)

{

Complex tmp;

tmp.a = this.a - rop.a;

tmp.b = this.b - rop.b;

return tmp; //这样返回会出问题

return rop;//这样返回没问题

}

*/

/************************************************************************/

//printf("%d", a[i]);

//a[i] = 10;

int& Array::operator[](int index) //函数返回值当左值 a[i] = 10;

{

????if (index > mLength)

????{

?

????}

????return mSpace[index];

}

?

//测试用例

//a2 = a3;

//a1 = a2 = a3;连等操作 =从右向左 先执行a2 = a3返回 a2再执行 a1 = a2;

//a1.operator=(a2.operator=(a3)))

//函数返回值当左值

Array& Array::operator=(Array &rop)

{

????if (mSpace != NULL)

????{

????????delete[]mSpace;

????????mLength = 0;

????????mSpace = NULL;

????}

????mSpace = new int[rop.mLength];

????mLength = rop.length();

????for (int i = 0; i < rop.mLength; ++i)

????{

????????mSpace[i] = rop.getData(i);

????}

????return *this;

}

bool Array::operator==(Array &rop)

{//先判断长度是否相等,在判断数据是否相等

????if (rop.length() != mLength)

????{

????????return false;

????}

????for (int i = 0; i < mLength; ++i)

????{

????????if (mSpace[i] != rop.getData(i))

????????{

????????????return false;

????????}

????}

????return true;

}

bool Array::operator!=(Array &rop)

{

????return !this->operator==(rop);

}

?

c++运算符重载

标签:

原文地址:http://www.cnblogs.com/lishuhuakai/p/4523481.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!