【例6.4】用友元函数重载运算符实现两字符串加法
C++教学 第9章+友元函数与运算符重载

float v1(A &a) { return PI*a.r*a.r*a.h;} //友元函数volum在类体外定义 float v3(A b) //普通函数 { return PI*b.getr()*b.getr()*b.geth();} void main() { A a1(25,40); A a2(25,40); cout<<v1(a1)<<"\n"; //友元函数的调用 cout <<a2.v2( )<<"\n"; cout<<v3(a1); }
对于大多数程序设计语言,运算符的定义由编译器给出,且 这种用法是不允许用户改变的。在C++中,允许用户重新定 义已有的运算符,并按规定要求去完成特定的操作。 使用成员函数或友元函数,通过操作对象成员,从而实现对 象参加运算的目的。
10
运算符重载函数的定义格式如下: (1)运算符重载函数定义为类的成员函数 函数类型 operator 运算符 (参数表) { …… }
15
9.3 一元运算符重载 C++中允许重载的一元运算符有: 自增运算符“++”、自减运算符“--”、 负号运算符“-”、逻辑非运算符“!”等。
16
9.3.1 用成员函数重载一元运算符
用成员函数重载“++”运算符的格式为: (1)++为前缀形式 函数类型 operator++(void) { 函数体 } (2)++为后缀形式 函数类型 operator++(int) { 函数体 } 重载自减运算符“--”的格式与重载“++”运算符类似。
第6章+运算符重载

}
其中,T1是运算符函数的返回类型,T2是参数的类型, 原则上T1、T2可以是任何数据类型,但事实上它 们常与X相同。
6.1.4 类运算符的重载
【例6-1】 有复数类Complex,利用运算符重载实现复数的加、减、 乘、除等复数运算。
//Eg6-1.cpp #include<iostream> using namespace std; class Complex { private: double r, i; public:
//...... };
Complex operator+(Complex a,Complex
b){……}
//定义
6.2 重载二元运算符
1、二元运算符的调用形式与解析 a@b 可解释成 a.operator@(b) 或解释成 operator@(a, b)
6.2.1 作为成员函数重载
class X{ ……
why?
使程序便于编写和阅读 使程序定义类型与语言内建类型更一致
how?
1.使用特殊的成员函数 2.使用自由函数,一般为友元函数
6.1.3 运算符重载的语法
运算符的计算结果是值,因此运算符函数是要返 回值的函数。其重载的语法形式如下:
返回类型 operator@(参数表)
//错误?
6.2.2 作为友元函数重载
2、重载二元运算符为类的友元函数时需要两个参数, 其形式Hale Waihona Puke 下:class X{ ……
friend T1 operator(T2 a,T3 b); }
T1 operator(T2 a,T3 b){ ……}
能用友元函数重载的运算符

能用友元函数重载的运算符
友元函数重载的运算符是一种常见的C++编程技术,可以使类的成员函数以及非成员函数来实现操作符的重载。
友元函数重载运算符可以被用于各种类,例如字符串、向量、复数等等。
使用友元函数重载运算符,我们可以自定义运算符的行为,使它们适用于我们的数据类型。
例如,我们可以重载加法运算符'+'以进行字符串连接,重载乘法运算符'*'以进行矩阵乘法,或者重载一元运算符'-'以取相反数。
由于友元函数可以访问类的私有成员,因此可以让我们设计更加精细的运算符重载。
在使用友元函数重载运算符时,需要注意避免对运算符进行过度重载,以免对代码的可读性和可维护性造成影响。
总之,友元函数重载运算符是一个功能强大的C++编程技术,可以使代码更加灵活以及易于理解和维护。
- 1 -。
友元与运算符重载

在上面的程序中,由于将长方体类定义为矩形类的友元,所以在长方体中,可以使用 矩形类中的私有数据成员计算长方体体积。
11.1.4 友元注意事项
(1)友元关系是不传递的Leabharlann 第 11 章 友元与运算符重载
友元函数可以是普通函数,也可以是某个类的成员函数,甚至可以将某个类说明成另 一个类的友元。下面就这三种友元进行讨论。
11.1.1 定义普通函数为友元函数
在定义一个类时,若在类中用关键词friend修饰普通函数,则该普通函数就成为该类的 友元函数,它可以访问该类中所有的成员。定义普通友元函数的格式为:
{ return r.Length*r.Width*High;}
在该函数内使用矩形对象 r 的私有数据成员 Length 与 Width 来计算长方体体积。由于
矩形对象 r 的私有数据成员不能在矩形类外使用,所以编译时会产生错误。解决问题的方法
之一就是将长方体类的成员函数 Volume()定义为矩形类的友元函数,即在矩形类中增加一
# include <iostream.h>
class Rectangle;
//A
class Cuboid
//B
{ private:
float High;
public:
Cuboid(float h)
{ High=h;}
float Volume(Rectangle &r);
//C
};
class Rectangle
friend <类型> <友元函数名> (形参表); 即:只要将用关键词 friend 修饰的普通函数原型说明写在类中,则该普通函数可以使用 类的所有成员。下面用例题进行说明。 【例 11.1】 用友元函数的方法求长方体的体积。 分析:先定义一个描述长方体的类 Cuboid,其私有数据成员为长方体的长(Length)、宽 (Width)、高(High),通过构造函数对长方体的数据成员进行初始化,见下列程序 A 行处。 再定义一个求长方体体积的普通函数 Volume(): float Volume(Cuboid &c) {return c.Length*c.Width*c.High;} 为了计算长方体对象 c 的体积,该函数的形参必须是长方体类的对象 c,并用该长方体 对象 c 的长、宽、高计算长方体的体积。由于 Volume()为普通函数,因此在其函数体内不 能使用长方体类 Cuboid 的私有数据成员 c.Length、c.Width、c.High,因而上述函数在编译 时会发生错误。解决问题方法之一就是将计算长方体体积的普通函数 Volume()定义为长方 体类的友元函数,即在长方体类 Cuboid 中增加一条将普通函数 Volume()定义成友元函数的 语句: friend float Volume(Cuboid &); 则在普通函数 Volume()内就可使用长方体类 Cuboid 的私有数据成员 c.Length、c.Width、 c.High。用友元函数方法求长方体体积的程序如下:
C++面向对象程序设计第七章运算符重载

7.2 重载++和--的前缀和后缀方式
【例7.6】用成员ห้องสมุดไป่ตู้数,区分单目运算符的前缀和后缀
【例7.7】用友元函数,区分单目运算符的前缀和后缀
16
【例7.1】 在复数complex类中重载运算符+(P186)
void main( ) #include <iostream.h> {complex c1(1,2),c2(3,4),c3; class complex c1.operator+(c2) ; c3= c1+c2; { private: //隐式调用形式 //这里的+采用类中重载后的含义 int real, imag; //定义复数的实部和虚部 //显式调用形式 } public: complex(int x=0, int y=0) { real=x; imag=y; } complex operator+ (complex c) //定义+运算符重载函数 { complex t; 函数名 t.real=real+c.real; //这里的+采用系统预定义含义 t.imag=imag+c.imag; return t; } };
19
【例7.2】用成员函数重载运算符的完整的复数类(P191) complex complex::operator +(complex c2) //重载运算符+函数实现 { double r=c2.real+real; double i=c2.imag+imag; return complex(r,i); } complex complex::operator -(complex c2) //重载运算符-函数实现 { double r=real-c2.real; double i=imag-c2.imag; return complex(r,i); }
字符串和字符的加操作

字符串和字符的加操作在计算机编程领域中,字符串和字符的加操作是常见的操作之一。
字符串是由多个字符组成的数据类型,而字符则是单个字符组成的数据类型。
在很多场景下,程序需要将多个字符串或字符进行拼接操作,以满足某些需求。
本篇文章将详细讨论字符串和字符的加操作。
首先,我们来看字符串的加操作。
字符串的加操作通常用于将多个字符串连接在一起,形成一个更长的字符串。
在大多数编程语言中,字符串的加操作可以使用加号(+)来实现。
例如,在Python语言中,我们可以使用以下代码实现字符串的加操作:```str1 = "Hello"str2 = "World"str3 = str1 + " " + str2print(str3)```在上面的代码中,我们定义了两个字符串变量str1和str2,并将它们拼接在一起,生成一个新的字符串str3。
在拼接过程中,我们使用了空格,以避免两个字符串之间没有间隔。
类似地,在Java语言中,我们也可以使用加号实现字符串的加操作。
例如:```String str1 = "Hello";String str2 = "World";String str3 = str1 + " " + str2;System.out.println(str3);```在上面的代码中,我们同样定义了两个字符串变量str1和str2,并将它们拼接在一起,生成一个新的字符串str3。
需要注意的是,字符串的加操作并不是所有编程语言都支持的。
例如,在C语言中,字符串的拼接操作需要使用strcpy()和strcat ()等函数来实现。
接下来,让我们来看看字符的加操作。
字符的加操作通常用于将多个字符连接在一起,形成一个更长的字符串。
在大多数编程语言中,字符的加操作同样可以使用加号(+)来实现。
例如,在Python语言中,我们可以使用以下代码实现字符的加操作:```char1 = 'H'char2 = 'i'char3 = char1 + char2print(char3)```在上面的代码中,我们定义了两个字符变量char1和char2,并将它们拼接在一起,生成一个新的字符char3。
C++重载(主要介绍使用友元函数重载)

C++重载(主要介绍使⽤友元函数重载)重载限制多数C++运算符都可以⽤下⾯的⽅式重载。
重载的运算符不必是成员函数,但必须⾄少有⼀个操作数是⽤户⾃定义的类型。
下⾯详细介绍C++对⽤户定义的运算符重载的限制。
1 重载后的运算符必须⾄少有⼀个操作数是⽤户⾃定义的类型,这将防⽌⽤户为标准类型重载运算符。
因此,不能将减法运算符(-)重载为double值的和,⽽不是它们的差。
虽然这种限制将对创造性有所影响,但可以确保程序正常运⾏。
2 使⽤运算符时不能违反运算符原来的句法规则。
例如,不能将求模运算符(%)重载成使⽤⼀个操作数。
同样,不能修改运算符的优先级。
因此,如果将加号运算符重载成将两个类相加,则新的运算符与原来的加号具有相同的优先级。
3 不能创建新的运算符。
例如,不能定义operator**()函数来表⽰求幂。
4 不能重载下⾯的运算符sizeof:sizeof运算符.:成员运算符.*:成员指针运算符:: :作⽤域解析运算符?::条件运算符typeid:⼀个RTTI运算符const_cast:强制类型转换运算符dynamic_cast:强制类型转换运算符reinterpret_cast:强制类型转换运算符static_cast:强制类型转换运算符然⽽,下表中的所有运算符都可以被重载5 下表中的⼤多数运算符都可以通过成员或⾮成员函数进⾏重载,但下⾯的运算符值能通过成员函数进⾏重载=:赋值运算符():函数调⽤运算符[]:下标运算符->:通过指针访问类成员的运算符可重载的运算符除了这些正式限制之外,还应在重载运算符时遵循⼀些限制。
例如,不要将*运算符重载成交换两个对象的数据成员。
友元C++控制对类对象私有部分的访问。
通常,公有类⽅法提供唯⼀的访问途径,这种限制太严格,以⾄于不适合特定的编程问题。
在这种情况下,C++提供了另外⼀种形式的访问权限:友元。
友元有3种:友元函数友元类友元成员函数通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。
C++运算符重载模板友元newdelete++=+=

C++运算符重载模板友元newdelete++=+=今天的重载是基于C++ 类模板的,如果需要⾮类模板的重载的朋友可以把类模板拿掉,同样可以参考,谢谢。
⼀、类模板中的友元重载本⼈喜好类声明与类成员实现分开写的代码风格,如若您喜欢将类成员函数的实现写在类声明中,那么可以跳过该部分。
请看下⾯这段代码:头⽂件:#pragma oncetemplate<typename T>class CLA{T m_value;public:CLA(const T&);friend CLA operator+(const CLA&, const CLA&);};template<typename T>CLA<T>::CLA(const T& a):m_value(a){ }template<typename T>CLA<T> operator+(const CLA<T>& lhs, const CLA<T>& rhs){return CLA<T>(lhs.m_value + rhs.m_value);}源⽂件:(已包含上述的头⽂件)int main(){CLA<int> a{ 0 }, b{ 1 }, c{ 2 };a + b;return0;}我们去执⾏上述代码的时候,编译器就会报错:⼀个⽆法解析的外部指令。
当然,将实现放⼊声明中是可以的,但是为了维护类的书写风格,我们还是希望有⼀种⽅法可以去维护这个风格。
那么我们可以将类中友元函数的声明写成如下形式:friend CLA operator+<T>(const CLA&, const CLA&);原因很简单,类模板具有抽象性,⽽刚刚那个友元函数就是普通的函数,不具有模板的抽象性。
即使参数为CLA<T> ... 还是⼀样,它代表的只不过是⼀个参数的类型,函数本⾝依旧是⼀个普通的函数。