面向对象3(信工)
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
. .* :: ?:
只能重载C++语言中已有的运算符, 不可臆造新的。
不改变原运算符的优先级和结合性。
不能改变操作数个数。
经重载的运算符,其操作数中至少应 该有一个是自定义类型。
21
两种形式
运
算 符
重载为类成员函数。
重 重载为友元函数。
载
22
运算符函数
运 算 符 重 载
声明形式 函数类型 { ...... }
int main() //主函数 { complex c1(3,4),c(5,-10),c3; //声明复数类的对象
c3=c1+c2; //使用重载运算符完成复数加法 cout<<"c1="; c1.display(); cout<<"c2="; c2.display(); cout<<"c1+c2="; c3.display(); return 0; }
//Error x: cannot access private member declared in class 'Point'
cout<<"y="<<p.y<<endl;
// Error y: cannot access private member declared in class 'Point'
友元定义重载运算符时,所有的操作对象
需要参数来传递。
30
运算符友元函数的设计
运 算 符
双目运算符 B重载后, 表达式oprd1 B oprd2 等同于operator B(oprd1,oprd2 )
重 载
前置单目运算符 B重载后, 表达式 B oprd
等同于operator B(oprd )
– 实部和虚部分别相加。
操作数:
– 两个操作数都是复数类的对象。
25
#include<iostream>
using namespace std; class complex //复数类声明 {
public: //外部接口 complex(double r=0.0,double i=0.0){real=r;imag=i;}
//构造函数 complex operator + (complex c2); //+重载为成员函数 void display(); //输出复数 private: //私有数据成员 double real; //复数实部 double imag; //复数虚部 };
26
complex complex::operator +(complex &c2) //重载函数实现
36
友元成员
一个类的成员函数作为另一个类的友元; 在声明友元成员函数时要加上成员函数所在的类
友 名和作用域运算符::,格式如下:
friend 函数返回类型 类名::函数名(参数表);
元 例3.1.2:教师修改学生成绩。
类的“提前引用”声明,只包含类名,不包含类 体;
类的提前引用声明只供类名的使用,不能创建对 象;
void display(); //显示复数的值
private:
double real;
double imag;
};
18
问题举例——复数的运算
运
算 用“+”、“-”能够实现复数的加减运
符 重
算吗?
载 实现复数加减运算的方法
——重载“+”、“-”运算符
19
运算符重载的实质
运
算 运算符重载是对已有的运算符赋予多重含义
A是B的友元,B是C的友元,但A不 一定是C的友元; 不继承:基类的友元并不能由其派 生类继承。
12
慎用友元
友元使原来松耦合的类之间变成紧
友
耦合,因此可能使调试程序变得困
难,程序的模块性也被破坏;
元 因而,友元是对封装和信息隐藏概
念的“杀手” ;
建议:Do not use “friend” if not necessary.
}
void main( )
{ Point p1(100,100), p2(20,20);
show(p1);
show(p2);
}
4
友元的定义
友 将某个外界对象说明为某一个类的友元,这个
外界对象就可以访问这个类对象中的私有成员
元 了;
声明为友元的外界对象既可以是另一个类的成 员函数,也可以是不属于任何类的一般函数, 还可以是整个的另一个类。
#include <iostream.h>
#include <iomanip.h>
class Point
{ int x, y;
public:
Point( ) {x=0;y=0;}
Point(int px, int py) {x=px;y=py;} };
void show(Point p)
{ cout<< “x=”<<p.x<<endl;
后置单目运算符 ++和--重载后, 表达式 oprd B 等同于operator B(oprd,0 )
31
例3.2.6
运
算 将+(双目)重载为复数类的友元函
符 重
数。
载 两个操作数都是复数类的对象。
32
#include<iostream>
using namespace std;
载 例3.2.4: 编写一个求两数相加的函数,
使用重载来实现三种类型数据(整数、 实数、字符串)的相加。
重载是在编译时寻找最匹配的函数版本, 体现了编译时的多态性。
17
问题举例——复数的运算
运
算 class complex
//复数类声明
符{ public:
重 complex(double r=0.0,double i=0.0) //构造函数 载 { real=r; imag=i; }
int GetX() {return X;}
int GetY() {return Y;}
friend float Distance(Point &a, Point &b);
private: //私有数据成员
int X,Y;
};
8
double Distance( Point& a, Point& b) {
double dx=a.X-b.X; double dy=a.Y-b.Y; return sqrt(dx*dx+dy*dy); } int main() { Point p1(3.0, 5.0), p2(4.0, 6.0); double d=Distance(p1, p2); cout<<"The distance is "<<d<<endl; return 0; }
13
3.2 重载
什么是重载(overloading)?同一符号
在同一作用域的不同场合具有不同的语 义。这个符号可以是函数名、运算符, 重载使程序更简洁。
函数重载 运算符重载
14
函数重载的概念
函数的名字问题:
重 – C++可以有多个构造函数,以便根据不同的
情况来构造对象,它们的名字相同!
载 – C++需要支持(解决)函数重名 构造函数可以重名 其他成员函数、全局函数也可以重名 只要参数不同,只要存在的范围不同 技术被称为“函数重载” – 另一个理由:将语义、功能相似的几个函数 用同一个名字表示,可以便于记忆,提高函 数的易用性和程序的可读性。 15
成员函数重载
重Leabharlann 面向对象的C++程序设计基础
友元、重载和引用
本章主要内容
友元(friend):即类的朋友,不同类 的成员函数之间、类的成员函数与一 般函数进行数据共享的机制;
重载(overloading):同一“符号” 在同一作用域的不同场合具有不同的 语义(实现算法);
引用(reference):即对象的别名。
符 必要性
重
– C++中预定义的运算符其运算对象只能是基本数
载 据类型,而不适用于用户自定义类型(如类)
实现机制
– 将指定的运算表达式转化为对运算符函数的调 用,运算对象转化为运算符函数的实参。
– 编译系统对重载运算符的选择,遵循函数重载 的选择原则。
20
规则和限制
运
算 符 重 载
可以重载C++中除下列运算符外的所 有运算符:
operator 运算符(形参)
重载为类成员函数时 参数个数=原操作数个数-1(后置++、--除外)
重载为友元函数时 参数个数=原操作数个数, 且至少应该有一个自定义类型的形参。
23
运算符成员函数的设计
运
算 双目运算符 B
符 重 载
– 如果要重载 B 为类成员函数,使之能够实 现表达式 oprd1 B oprd2,其中 oprd1 为A
任何对象的定义都要在类的定义体之后。
10
友元类
友元可以是一个类;
当一个类是另一个类的友元时,它的所有成员函
友 数都成为另一个类的友元函数,即作为友元的类
中的所有成员函数都可以访问另一个类中的私有
元
成员; 格式为:friend
class
类名;
在A类的定义体中:friend class B;//B是A的友元。
例3.1.4:输入10个数,求其最大值和最小值。
注:类的友元关系是不能传递的,即A是B的友元, B是C的友元,但A不一定是C的友元。友元也不 具有交换性,A是B的友元,但B不一定是A的友 元。
11
友元的特性
友 不对称:如果A是B的友元,但B不
一定是A的友元;
元 不传递:友元关系不能传递,如果
};
6
友元函数
一个类的友元函数,不是当前类的成员函数,而是
友 独立于当前类的一般的外部函数,但它可以访问该 类中所有对象的私有成员;
元 友元函数在类内声明,其函数名前加上关键词 friend,可以在公有或私有部分声明,格式如下: friend 函数返回类型 函数名(参数表); 友元函数的定义可以在类内、类外,类外定义时和 一般函数的定义一样; 友元函数的调用不需要通过对象或指向对象的指针, 而用一般的函数调用形式。 例3.1.1,友元函数的定义。
28
程序输出的结果为: c1=(3,4i) c2=(5,-10i) c1+c2=(8,-6i)
29
重载为类的友元函数
运
算 符
运算符重载形式与重载为类的成员函数相 同,只是参数表中的参数要求不同;
重 单目运算符要求1个操作数,双目运算符要
载 求2个操作数,对同一个运算符,重载为成
员函数总比重载为友元函数时少一个参数。
类对象,则 B 应被重载为 A 类的成员函数
,形参类型应该是 oprd2 所属的类型。
– 经重载后,表达式 oprd1 B oprd2 相当于
oprd1.operator B(oprd2)
24
例3.2.5:重载运算符“+” ,用于两个
复数相加。
运
算
将“+” 运算重载为复数类的成员
符 函数。
重 载 规则:
2
友元的概念
友 类的特点是数据隐藏,即类的私有数据只
元
有通过其成员函数访问。当频繁访问类的 私有成员时,函数调用将使程序的开销很
大;
C++提供了一种方法---“友元”机制,可 以破坏封装性,即允许外面的类或函数访 问另一个类中的私有成员(数据和成员函 数),这就是友元;
友元用friend声明。 3
7
例: 使用友元函数计算两点距离
#include <iostream>
友 #include <cmath> using namespace std;
元 class Point //Point类声明 { public: //外部接口
Point(int xx=0, int yy=0) {X=xx;Y=yy;}
友元声明部分包含在其私有成员可被访问的类 的定义体中。此声明可放在公有部分,也可放 在私有部分。
例子:
5
class Point { int x,y;
public: friend void show (Point p); //show是Point类的友元函数 friend class line; //line是Point类的友元类
{ complex c; c.real=c2.real+real; c.imag=c2.imag+imag; return complex(c.real,c.imag);
}
27
void complex::display() { cout<<"("<<real<<","<<imag<<“I”<<“)"<<endl; }
载
与构造函数一样,成员函数可以重载, 依靠所包含的参数的类型与个数的差异 进行区分;
初始化对象时不传递或传递不同的参数, 以实现匹配调用。
例3.2.2:在类中重载“输出”成员函数, 根据参数不同,执行不同的操作。
16
非成员函数重载
类以外的一般函数也允许重载,和成员
重 函数的重载规则是一致的。
只能重载C++语言中已有的运算符, 不可臆造新的。
不改变原运算符的优先级和结合性。
不能改变操作数个数。
经重载的运算符,其操作数中至少应 该有一个是自定义类型。
21
两种形式
运
算 符
重载为类成员函数。
重 重载为友元函数。
载
22
运算符函数
运 算 符 重 载
声明形式 函数类型 { ...... }
int main() //主函数 { complex c1(3,4),c(5,-10),c3; //声明复数类的对象
c3=c1+c2; //使用重载运算符完成复数加法 cout<<"c1="; c1.display(); cout<<"c2="; c2.display(); cout<<"c1+c2="; c3.display(); return 0; }
//Error x: cannot access private member declared in class 'Point'
cout<<"y="<<p.y<<endl;
// Error y: cannot access private member declared in class 'Point'
友元定义重载运算符时,所有的操作对象
需要参数来传递。
30
运算符友元函数的设计
运 算 符
双目运算符 B重载后, 表达式oprd1 B oprd2 等同于operator B(oprd1,oprd2 )
重 载
前置单目运算符 B重载后, 表达式 B oprd
等同于operator B(oprd )
– 实部和虚部分别相加。
操作数:
– 两个操作数都是复数类的对象。
25
#include<iostream>
using namespace std; class complex //复数类声明 {
public: //外部接口 complex(double r=0.0,double i=0.0){real=r;imag=i;}
//构造函数 complex operator + (complex c2); //+重载为成员函数 void display(); //输出复数 private: //私有数据成员 double real; //复数实部 double imag; //复数虚部 };
26
complex complex::operator +(complex &c2) //重载函数实现
36
友元成员
一个类的成员函数作为另一个类的友元; 在声明友元成员函数时要加上成员函数所在的类
友 名和作用域运算符::,格式如下:
friend 函数返回类型 类名::函数名(参数表);
元 例3.1.2:教师修改学生成绩。
类的“提前引用”声明,只包含类名,不包含类 体;
类的提前引用声明只供类名的使用,不能创建对 象;
void display(); //显示复数的值
private:
double real;
double imag;
};
18
问题举例——复数的运算
运
算 用“+”、“-”能够实现复数的加减运
符 重
算吗?
载 实现复数加减运算的方法
——重载“+”、“-”运算符
19
运算符重载的实质
运
算 运算符重载是对已有的运算符赋予多重含义
A是B的友元,B是C的友元,但A不 一定是C的友元; 不继承:基类的友元并不能由其派 生类继承。
12
慎用友元
友元使原来松耦合的类之间变成紧
友
耦合,因此可能使调试程序变得困
难,程序的模块性也被破坏;
元 因而,友元是对封装和信息隐藏概
念的“杀手” ;
建议:Do not use “friend” if not necessary.
}
void main( )
{ Point p1(100,100), p2(20,20);
show(p1);
show(p2);
}
4
友元的定义
友 将某个外界对象说明为某一个类的友元,这个
外界对象就可以访问这个类对象中的私有成员
元 了;
声明为友元的外界对象既可以是另一个类的成 员函数,也可以是不属于任何类的一般函数, 还可以是整个的另一个类。
#include <iostream.h>
#include <iomanip.h>
class Point
{ int x, y;
public:
Point( ) {x=0;y=0;}
Point(int px, int py) {x=px;y=py;} };
void show(Point p)
{ cout<< “x=”<<p.x<<endl;
后置单目运算符 ++和--重载后, 表达式 oprd B 等同于operator B(oprd,0 )
31
例3.2.6
运
算 将+(双目)重载为复数类的友元函
符 重
数。
载 两个操作数都是复数类的对象。
32
#include<iostream>
using namespace std;
载 例3.2.4: 编写一个求两数相加的函数,
使用重载来实现三种类型数据(整数、 实数、字符串)的相加。
重载是在编译时寻找最匹配的函数版本, 体现了编译时的多态性。
17
问题举例——复数的运算
运
算 class complex
//复数类声明
符{ public:
重 complex(double r=0.0,double i=0.0) //构造函数 载 { real=r; imag=i; }
int GetX() {return X;}
int GetY() {return Y;}
friend float Distance(Point &a, Point &b);
private: //私有数据成员
int X,Y;
};
8
double Distance( Point& a, Point& b) {
double dx=a.X-b.X; double dy=a.Y-b.Y; return sqrt(dx*dx+dy*dy); } int main() { Point p1(3.0, 5.0), p2(4.0, 6.0); double d=Distance(p1, p2); cout<<"The distance is "<<d<<endl; return 0; }
13
3.2 重载
什么是重载(overloading)?同一符号
在同一作用域的不同场合具有不同的语 义。这个符号可以是函数名、运算符, 重载使程序更简洁。
函数重载 运算符重载
14
函数重载的概念
函数的名字问题:
重 – C++可以有多个构造函数,以便根据不同的
情况来构造对象,它们的名字相同!
载 – C++需要支持(解决)函数重名 构造函数可以重名 其他成员函数、全局函数也可以重名 只要参数不同,只要存在的范围不同 技术被称为“函数重载” – 另一个理由:将语义、功能相似的几个函数 用同一个名字表示,可以便于记忆,提高函 数的易用性和程序的可读性。 15
成员函数重载
重Leabharlann 面向对象的C++程序设计基础
友元、重载和引用
本章主要内容
友元(friend):即类的朋友,不同类 的成员函数之间、类的成员函数与一 般函数进行数据共享的机制;
重载(overloading):同一“符号” 在同一作用域的不同场合具有不同的 语义(实现算法);
引用(reference):即对象的别名。
符 必要性
重
– C++中预定义的运算符其运算对象只能是基本数
载 据类型,而不适用于用户自定义类型(如类)
实现机制
– 将指定的运算表达式转化为对运算符函数的调 用,运算对象转化为运算符函数的实参。
– 编译系统对重载运算符的选择,遵循函数重载 的选择原则。
20
规则和限制
运
算 符 重 载
可以重载C++中除下列运算符外的所 有运算符:
operator 运算符(形参)
重载为类成员函数时 参数个数=原操作数个数-1(后置++、--除外)
重载为友元函数时 参数个数=原操作数个数, 且至少应该有一个自定义类型的形参。
23
运算符成员函数的设计
运
算 双目运算符 B
符 重 载
– 如果要重载 B 为类成员函数,使之能够实 现表达式 oprd1 B oprd2,其中 oprd1 为A
任何对象的定义都要在类的定义体之后。
10
友元类
友元可以是一个类;
当一个类是另一个类的友元时,它的所有成员函
友 数都成为另一个类的友元函数,即作为友元的类
中的所有成员函数都可以访问另一个类中的私有
元
成员; 格式为:friend
class
类名;
在A类的定义体中:friend class B;//B是A的友元。
例3.1.4:输入10个数,求其最大值和最小值。
注:类的友元关系是不能传递的,即A是B的友元, B是C的友元,但A不一定是C的友元。友元也不 具有交换性,A是B的友元,但B不一定是A的友 元。
11
友元的特性
友 不对称:如果A是B的友元,但B不
一定是A的友元;
元 不传递:友元关系不能传递,如果
};
6
友元函数
一个类的友元函数,不是当前类的成员函数,而是
友 独立于当前类的一般的外部函数,但它可以访问该 类中所有对象的私有成员;
元 友元函数在类内声明,其函数名前加上关键词 friend,可以在公有或私有部分声明,格式如下: friend 函数返回类型 函数名(参数表); 友元函数的定义可以在类内、类外,类外定义时和 一般函数的定义一样; 友元函数的调用不需要通过对象或指向对象的指针, 而用一般的函数调用形式。 例3.1.1,友元函数的定义。
28
程序输出的结果为: c1=(3,4i) c2=(5,-10i) c1+c2=(8,-6i)
29
重载为类的友元函数
运
算 符
运算符重载形式与重载为类的成员函数相 同,只是参数表中的参数要求不同;
重 单目运算符要求1个操作数,双目运算符要
载 求2个操作数,对同一个运算符,重载为成
员函数总比重载为友元函数时少一个参数。
类对象,则 B 应被重载为 A 类的成员函数
,形参类型应该是 oprd2 所属的类型。
– 经重载后,表达式 oprd1 B oprd2 相当于
oprd1.operator B(oprd2)
24
例3.2.5:重载运算符“+” ,用于两个
复数相加。
运
算
将“+” 运算重载为复数类的成员
符 函数。
重 载 规则:
2
友元的概念
友 类的特点是数据隐藏,即类的私有数据只
元
有通过其成员函数访问。当频繁访问类的 私有成员时,函数调用将使程序的开销很
大;
C++提供了一种方法---“友元”机制,可 以破坏封装性,即允许外面的类或函数访 问另一个类中的私有成员(数据和成员函 数),这就是友元;
友元用friend声明。 3
7
例: 使用友元函数计算两点距离
#include <iostream>
友 #include <cmath> using namespace std;
元 class Point //Point类声明 { public: //外部接口
Point(int xx=0, int yy=0) {X=xx;Y=yy;}
友元声明部分包含在其私有成员可被访问的类 的定义体中。此声明可放在公有部分,也可放 在私有部分。
例子:
5
class Point { int x,y;
public: friend void show (Point p); //show是Point类的友元函数 friend class line; //line是Point类的友元类
{ complex c; c.real=c2.real+real; c.imag=c2.imag+imag; return complex(c.real,c.imag);
}
27
void complex::display() { cout<<"("<<real<<","<<imag<<“I”<<“)"<<endl; }
载
与构造函数一样,成员函数可以重载, 依靠所包含的参数的类型与个数的差异 进行区分;
初始化对象时不传递或传递不同的参数, 以实现匹配调用。
例3.2.2:在类中重载“输出”成员函数, 根据参数不同,执行不同的操作。
16
非成员函数重载
类以外的一般函数也允许重载,和成员
重 函数的重载规则是一致的。