第11章77 运算符重载
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
会引起内存泄漏 使这两个数组的元素存放于同一块空间中
当这两个对象析构时,先析构的对象会释放 存储数组元素的空间。而当后一个对象析构 时,无法释放存放数组元素的空间
赋值运算符“=”的原型
赋值运算符只能重载成成员函数 函数原型:
X &X::operator=(const X &source) { // 赋值过程 }
赋值运算符
对任一类,如果用户没有自定义赋值运算 符函数,那么系统为其生成一个缺省的赋 值运算符函数,在对应的数据成员间赋值。
一般情况下,这个缺省的赋值运算符重载 函数能满足用户的需求。但是,当类含有 类型为指针的数据成员时,可能会带来一 些麻烦。
对DoubleArray类对象执行 array1 = array2的问题
全局函数 vs成员函数
大多数运算符都可以重载成成员函数或全局函数。 赋值(=)、下标([])函数调用(())和成员访问(->)
必须重载成成员函数。 具有赋值意义的运算符,如复合的赋值运算符以及++和--,
不一定非要定义为成员函数,但最好定义为成员函数。 具有两个运算对象的运算符最好重载为全局函数,这样可
bool Rational::operator>(const Rational &r1) const { return num * r1.den > den * r1.num; }
bool Rational::operator<=(const Rational &r1) const { return num * r1.den <= den * r1.num; }
运算符重载可以重载成成员函数也可以重载成全局函数实现。 重载成全局函数时,最好把此函数设为友员函数
如果作为类的成员函数,它的形式参数个数比运算符的运算 对象数少1。这是因为成员函数有一个隐含的参数this。在 C++中,把隐含参数this作为运算符的第一个参数。
当把一个一元运算符重载成成员函数时,该函数没有形式参 数。
把一个二元运算符重载成成员函数时,该函数只有一个形式 参数,就是右操作数,当前对象是左操作数。
重载实例
为rational类增加“+”和“*”以及比较的重 载函数,用以替换现有的add和multi函数
方案一:重载成成员函数
class Rational { private:
int num; int den; void ReductFraction(); public: Rational(int n = 0, int d = 1) { num = n; den = d;}
赋值运算符重载和拷贝构造函数
一般来讲,需要拷贝构造函数的类也需要 重载赋值运算符
定义对象时给对象赋初值调用的是拷贝构 造函数
程序的语句部分中的赋值语句调用的是赋 值运算符重载函数
几个特殊的运算符的重载
赋值运算符 下标运算符 函数调用运算符 ++和—运算符的重载 重载函数的原型设计考虑 输入输出运算符重载
Rational operator*(const Rational &r1, const Rational &r2) { Rational tmp;
tmp.num = r1.num * r2.num; tmp.den = r1.den * r2.den; tmp.ReductFraction(); return tmp; } 其他函数实现略
private: int num; int den; void ReductFraction();
public: Rational(int n = 0, int d = 1) { num = n; den = d;} void display() { cout << num << '/' << den;}
第11章77 运算符重载
什么是运算符重载
使系统内置的运算符可以用于类类型 例如:+ 运算符能够实现2个对象间的加。
例如:类A的对象a1、a2、a3,希望: a3 = a1 + a2; 即:分别把对象a1和a2的各个数据成员值 对应相加,然后赋给对象a3。
问题的提出
把某些事交给系统去做,用户只要知道相 加就可
};
函数的实现
Rational operator+(const Rational &r1, const Rational &r2) { Rational tmp;
tmp.num = r1.num * r2.den + r2.num * r1.den; tmp.den = r1.den * r2.den; tmp.ReductFraction(); return tmp; }
不能重载的运算符
. .* :: ?: sizeof
第11章 运算符重载
什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例
运算符重载的方法
运算符重载就是写一个函数解释某个运算符在 某个类中的含义
要使得系统能自动找到重载的这个函数,函数 名必须要体现出和某个被重载的运算符的联系。
方案二:重载成友员函数
class Rational { friend Rational operator+(const Rational &r1, const Rational &r2); friend Rational operator*(const Rational &r1 , const Rational &r2); friend bool operator<(const Rational &r1 , const Rational &r2) ; friend bool operator==(const Rational &r1 , const Rational &r2); friend bool operator>(const Rational &r1 , const Rational &r2) ; friend bool operator<=(const Rational &r1 , const Rational &r2); friend bool operator>=(const Rational &r1 , const Rational &r2); friend bool operator!=(const Rational &r1 , const Rational &r2) ;
Rational operator+(const Rational &r1) const; Rational operator*(const Rational &r1) const; bool operator<(const Rational &r1) const; bool operator==(const Rational &r1) const; bool operator>(const Rational &r1) const; bool operator<=(const Rational &r1) const; bool operator>=(const Rational &r1) const; bool operator!=(const Rational &r1) const; void display() { cout << num << '/' << den; } }
bool Rational::operator<(const Rational &r1) const { return num * r1.den < den * r1.num; }
bool Rational::operator==(const Rational &r1) const { return num == r1.num && den == r1.den;}
Rational Rational::operator*(const Rational &r1) const { Rational tmp;
tmp.num = num * r1.num; tmp.den = den * r1.den; tmp.ReductFraction(); return tmp; }
以使得应用更加灵活。如果把加运算定义成全局函数,r是 有理数类的对象,则2+r是一个合法的表达式。
第11章 运算符重载
什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例
几个特殊的运算符的重载
赋值运算符 下标运算符 函数调用运算符 ++和—运算符的重载 重载函数的原型设计考虑 输入输出运算符重载
一旦创建了对象x1, x2, 可以用 xຫໍສະໝຸດ Baidu = x2赋值。
DoubleArray类的 赋值运算符重载函数
DoubleArray &DoubleArray::operator= (const DoubleArray &right)
{ if (this == &right) return *this; delete [ ] storage; low = right.low; high = right.high; storage = new double[high - low + 1]; for (int i=0; i <= high - low; ++i) storage[i] = right.storage[i]; //复制数组元素 return *this;
重载后有理数类的使用
int main() { Rational r1(1,6), r2(1,6), r3;
r3 = r1 + r2; r1.display(); cout << " + "; r2.display(); cout << " = "; r3.display(); cout << endl; r3 = r1 * r2; r1.display(); cout << " * "; r2.display(); cout << " = "; r3.display(); cout << endl; return 0; }
bool Rational::operator>=(const Rational &r1) const { return num * r1.den >= den * r1.num; }
bool Rational::operator!=(const Rational &r1) const { return !(*this == r1);}
C++中规定,重载函数名为 operator@ 其中,@为要重载的运算符。如要重载“+”运
算符,该重载函数名为operator+。要重载赋值 运算符,函数名为operator=。
函数原型
运算符的重载不能改变运算符的运算对象数。因此,重载函 数的形式参数个数(包括成员函数的隐式指针this)与运算 符的运算对象数相同
}
赋值运算符重载要点
一般来讲,需要自定义拷贝构造函数的类也需要 自定义赋值运算符重载函数。
在赋值运算符重载函数中,已经将参数的值赋值 给了当前对象,那为什么还需要返回值呢?记住, 在C++中,赋值是一个运算,它可以形成一个表 达式,而该表达式的结果值就是赋给左边的对象 的值。因此,赋值运算符重载函数必须返回赋给 左边的对象值。
函数实现
Rational Rational::operator+(const Rational &r1) const { Rational tmp;
tmp.num = num * r1.den + r1.num * den; tmp.den = den * r1.den; tmp.ReductFraction(); return tmp; }
扩充运算符的功能 增强了C++ 语言的可扩充性 使用户定义的类更像系统的内置类型
运算符重载的限制
不是所有的运算符都能重载 重载不能改变运算符的优先级和结合性 重载不能改变运算符的操作数个数 不能创建新的运算符
可以重载的运算符
+ - * / % ^ &| ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete new[] delete[]
当这两个对象析构时,先析构的对象会释放 存储数组元素的空间。而当后一个对象析构 时,无法释放存放数组元素的空间
赋值运算符“=”的原型
赋值运算符只能重载成成员函数 函数原型:
X &X::operator=(const X &source) { // 赋值过程 }
赋值运算符
对任一类,如果用户没有自定义赋值运算 符函数,那么系统为其生成一个缺省的赋 值运算符函数,在对应的数据成员间赋值。
一般情况下,这个缺省的赋值运算符重载 函数能满足用户的需求。但是,当类含有 类型为指针的数据成员时,可能会带来一 些麻烦。
对DoubleArray类对象执行 array1 = array2的问题
全局函数 vs成员函数
大多数运算符都可以重载成成员函数或全局函数。 赋值(=)、下标([])函数调用(())和成员访问(->)
必须重载成成员函数。 具有赋值意义的运算符,如复合的赋值运算符以及++和--,
不一定非要定义为成员函数,但最好定义为成员函数。 具有两个运算对象的运算符最好重载为全局函数,这样可
bool Rational::operator>(const Rational &r1) const { return num * r1.den > den * r1.num; }
bool Rational::operator<=(const Rational &r1) const { return num * r1.den <= den * r1.num; }
运算符重载可以重载成成员函数也可以重载成全局函数实现。 重载成全局函数时,最好把此函数设为友员函数
如果作为类的成员函数,它的形式参数个数比运算符的运算 对象数少1。这是因为成员函数有一个隐含的参数this。在 C++中,把隐含参数this作为运算符的第一个参数。
当把一个一元运算符重载成成员函数时,该函数没有形式参 数。
把一个二元运算符重载成成员函数时,该函数只有一个形式 参数,就是右操作数,当前对象是左操作数。
重载实例
为rational类增加“+”和“*”以及比较的重 载函数,用以替换现有的add和multi函数
方案一:重载成成员函数
class Rational { private:
int num; int den; void ReductFraction(); public: Rational(int n = 0, int d = 1) { num = n; den = d;}
赋值运算符重载和拷贝构造函数
一般来讲,需要拷贝构造函数的类也需要 重载赋值运算符
定义对象时给对象赋初值调用的是拷贝构 造函数
程序的语句部分中的赋值语句调用的是赋 值运算符重载函数
几个特殊的运算符的重载
赋值运算符 下标运算符 函数调用运算符 ++和—运算符的重载 重载函数的原型设计考虑 输入输出运算符重载
Rational operator*(const Rational &r1, const Rational &r2) { Rational tmp;
tmp.num = r1.num * r2.num; tmp.den = r1.den * r2.den; tmp.ReductFraction(); return tmp; } 其他函数实现略
private: int num; int den; void ReductFraction();
public: Rational(int n = 0, int d = 1) { num = n; den = d;} void display() { cout << num << '/' << den;}
第11章77 运算符重载
什么是运算符重载
使系统内置的运算符可以用于类类型 例如:+ 运算符能够实现2个对象间的加。
例如:类A的对象a1、a2、a3,希望: a3 = a1 + a2; 即:分别把对象a1和a2的各个数据成员值 对应相加,然后赋给对象a3。
问题的提出
把某些事交给系统去做,用户只要知道相 加就可
};
函数的实现
Rational operator+(const Rational &r1, const Rational &r2) { Rational tmp;
tmp.num = r1.num * r2.den + r2.num * r1.den; tmp.den = r1.den * r2.den; tmp.ReductFraction(); return tmp; }
不能重载的运算符
. .* :: ?: sizeof
第11章 运算符重载
什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例
运算符重载的方法
运算符重载就是写一个函数解释某个运算符在 某个类中的含义
要使得系统能自动找到重载的这个函数,函数 名必须要体现出和某个被重载的运算符的联系。
方案二:重载成友员函数
class Rational { friend Rational operator+(const Rational &r1, const Rational &r2); friend Rational operator*(const Rational &r1 , const Rational &r2); friend bool operator<(const Rational &r1 , const Rational &r2) ; friend bool operator==(const Rational &r1 , const Rational &r2); friend bool operator>(const Rational &r1 , const Rational &r2) ; friend bool operator<=(const Rational &r1 , const Rational &r2); friend bool operator>=(const Rational &r1 , const Rational &r2); friend bool operator!=(const Rational &r1 , const Rational &r2) ;
Rational operator+(const Rational &r1) const; Rational operator*(const Rational &r1) const; bool operator<(const Rational &r1) const; bool operator==(const Rational &r1) const; bool operator>(const Rational &r1) const; bool operator<=(const Rational &r1) const; bool operator>=(const Rational &r1) const; bool operator!=(const Rational &r1) const; void display() { cout << num << '/' << den; } }
bool Rational::operator<(const Rational &r1) const { return num * r1.den < den * r1.num; }
bool Rational::operator==(const Rational &r1) const { return num == r1.num && den == r1.den;}
Rational Rational::operator*(const Rational &r1) const { Rational tmp;
tmp.num = num * r1.num; tmp.den = den * r1.den; tmp.ReductFraction(); return tmp; }
以使得应用更加灵活。如果把加运算定义成全局函数,r是 有理数类的对象,则2+r是一个合法的表达式。
第11章 运算符重载
什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例
几个特殊的运算符的重载
赋值运算符 下标运算符 函数调用运算符 ++和—运算符的重载 重载函数的原型设计考虑 输入输出运算符重载
一旦创建了对象x1, x2, 可以用 xຫໍສະໝຸດ Baidu = x2赋值。
DoubleArray类的 赋值运算符重载函数
DoubleArray &DoubleArray::operator= (const DoubleArray &right)
{ if (this == &right) return *this; delete [ ] storage; low = right.low; high = right.high; storage = new double[high - low + 1]; for (int i=0; i <= high - low; ++i) storage[i] = right.storage[i]; //复制数组元素 return *this;
重载后有理数类的使用
int main() { Rational r1(1,6), r2(1,6), r3;
r3 = r1 + r2; r1.display(); cout << " + "; r2.display(); cout << " = "; r3.display(); cout << endl; r3 = r1 * r2; r1.display(); cout << " * "; r2.display(); cout << " = "; r3.display(); cout << endl; return 0; }
bool Rational::operator>=(const Rational &r1) const { return num * r1.den >= den * r1.num; }
bool Rational::operator!=(const Rational &r1) const { return !(*this == r1);}
C++中规定,重载函数名为 operator@ 其中,@为要重载的运算符。如要重载“+”运
算符,该重载函数名为operator+。要重载赋值 运算符,函数名为operator=。
函数原型
运算符的重载不能改变运算符的运算对象数。因此,重载函 数的形式参数个数(包括成员函数的隐式指针this)与运算 符的运算对象数相同
}
赋值运算符重载要点
一般来讲,需要自定义拷贝构造函数的类也需要 自定义赋值运算符重载函数。
在赋值运算符重载函数中,已经将参数的值赋值 给了当前对象,那为什么还需要返回值呢?记住, 在C++中,赋值是一个运算,它可以形成一个表 达式,而该表达式的结果值就是赋给左边的对象 的值。因此,赋值运算符重载函数必须返回赋给 左边的对象值。
函数实现
Rational Rational::operator+(const Rational &r1) const { Rational tmp;
tmp.num = num * r1.den + r1.num * den; tmp.den = den * r1.den; tmp.ReductFraction(); return tmp; }
扩充运算符的功能 增强了C++ 语言的可扩充性 使用户定义的类更像系统的内置类型
运算符重载的限制
不是所有的运算符都能重载 重载不能改变运算符的优先级和结合性 重载不能改变运算符的操作数个数 不能创建新的运算符
可以重载的运算符
+ - * / % ^ &| ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete new[] delete[]