大纲:
1. 运算符重载
3. 友元函数
4. 思考一个问题
先把Vector类的代码放出来
相比上次的Vector省略了一些
// Vector.h
#ifndef VECTOR_H
#define VECTOR_H
class Vector
{
private:
int x;
int y;
public:
void show() const;
};
#endif
// Vector.cpp
#include "Vector.h"
#include
void Vector::show() const
{
using namespace std;
cout << x << "," << y << endl;
return ;
}
。。。。。。
如果要把一个矢量相加减
你是否梦想着可以用下面的代码来实现呢?
//test.cpp
#include "Vector.h"
#include
using namespace std;
int main()
{
Vector v1(2,3);
Vector v2(3,4);
Vector vp;
Vector vm,vm2;
vp = v1 + v2;
vm = v1 * v2;
vm2 = 3 * vm;
cout << v;
return 0;
}
可是,Vector类对象并不是普通的内置类型
计算机并不知道如何将他们相加相乘
更不知道如何用cout将这个类输出
这个时候,全都需要我们自己定义运算符
两个double类型的数据可以用运算符+相加
两个int类型的数据也可以用运算符+相加
诶,+号就像函数一样
可以根据不同的参数类型执行不同的操作
其实,运算符重载和函数重载是一样的呢
再其实,运算符其实就是个函数
下面先放出一个运算符重载的实例
// 函数原型
Vector operator+(Vector v1,Vector v2);
// 函数定义
Vector operator+(Vector v1,Vector v2)
{
Vector temp;
temp.x = v1.x + v2.x;
temp.y = v1.y + v2.y;
return temp;
}
在这个函数定义中,
+号在函数里用了operator+表示
注意:这里说明了,运算符是可以有两种表示方式的
一种是运算符表示法: v = v1 + v2;
y一种是函数表示法:v = operator+(v1,v2);
然后其他的东东和普通的函数时一样的
可是,这个函数是不能用的
还记得以前说到的,
非成员函数,是不能够访问类的私有成员的
要解决这个问题
1. 在类中定义运算符重载
2. 友元函数
还记得以前说到的
类成员函数,会隐式的传递this指针
下面还是先给一个类中定义运算符重载的例子
Vector Vector::operator+(Vector v1)
{
Vector temp;
temp.x = v1.x + x;
temp.y = v1.y + y;
return temp;
}
区别:
1. 使用作用域解析运算符
2. 少传递了一个参数,原本需要两个操作数的+
只传递了一个对象?
在类中,会隐式的传递自身作为运算符的一个操作数
如:v = v1 + v2
用函数表示法可表示为
v = v1.operator+(v2);
对上面的问题,还有一种解决方案
虽然非成员函数无法访问类的私有成员
但我可以通过一种特殊的方式
让非成员函数获得访问私有成员的特权
友元函数!!
友元函数的语法要求有两个:
1. 函数的原型前面加上friend关键字
2. 函数原型必须放在类定义内部
下面给例子
// 函数原型
class Vector
{
...
public:
...
friend Vector operator+(Vector v1,Vector v2);
}
// 函数定义
Vector operator+(Vector v1,Vector v2)
{
Vector temp;
temp.x = v1.x + v2.x;
temp.y = v1.y + v2.y;
return temp;
}
函数的调用方式略有不同
v = v1 + v2;
实际上是这样的函数调用
v = operator+(v1, v2);
乘法和加法类似
也有友元版运算符重载
和类内运算符重载两种形式
不过有一个需要思考的
vm2 = 3 * v2
这个该怎么办呢?
在类内运算符重载中
二元运算符的第一个操作数是调用对象本身
第二个操作数是函数参数
如:v = v1 + v2
用函数表示法可表示为
v = v1.operator+(v2);
对vm2 = 3 * v2
只有通过定义一个友元函数才能够解决
因为 3 不是一个对象,
无法调用对象内的运算符函数来计算
只能够通过友元函数来实现
// 函数原型
class Vector
{
...
public:
...
friend Vector operator*(int d ,Vector v);
}
// 函数定义
Vector operator*(int d ,Vector v)
{
Vector temp;
temp.x = v.x * d;
temp.y = v.y * d;
return temp;
}
上面的运算符重载能否实现以下操作
v = v1 + v2 + v3 + v4;
运算符重载,是否能够重载任意运算符?
重载能否改变现有的运算规则
(比如把两个int类的+法自定义)
如何实现<< 的运算符重载从而实现
cout << v;
可以
假设这里用的是类内的运算符重载
根据+号从左往右结合
先算v1 + v2
v = v1.operator(v2) + v3 + v4;
然后根据函数定义
该函数返回一个Vector对象
也就是说
v1.operator(v2)
本身就是一个Vector 对象
然后这个对象与v3结合,再使用+号
v = v1.operator(v2).operator+(v3) + v4;
后面以此类推
关键是在该运算符函数返回对象(当然也可以返回对象的引用)
还是有很多限制的
比如:
1. 运算符操作数至少一个数是用户自定义的类型
2. 不违反现有的句法规则
3. 不创造新的运算符
4. 一部分运算符不可以重载
一部分运算符只能在类内作为类成员函数重载
一部分运算符类内类外均可
具体的可以自行了解
当然加减乘除都是类内类外均可的
哎呀……上面不小心回答完了
先放例子
// 函数原型
class Vector
{
...
public:
...
friend ostream & operator<<(ostream & os, const Vector & temp );
}
// 函数定义
ostream & operator<<(ostream & os, const Vector & temp )
{
os << temp.x << "," << temp.y << endl ;
return os;
}
详细解释看 c++ primer plus p392 - 394吧
不大好解释呢
反正……cin是一个ostream类的对象
所以要想
cin << v;
函数的形参列表就必须与上面对应
(见函数定义)
一些比较好的博客
http://blog.csdn.net/dingyuanpu/article/details/5852825
http://blog.csdn.net/zgl_dm/article/details/1767201