第五章 成员函数
C++中各种数据成员及成员函数的定义及使用
C++中各种数据成员及成员函数的定义及使⽤转载于:1.类是⾃定义的数据类型.类与应⽤程序不同,类的功能虽然独⽴,但不能独⽴启动,就象汽车零件那样.2.Class 是⼀种数据类型, 其变量为对象.对象包含有member variables(成员变量)和member1 functions(成员函数).2class Date{3int year, month, day;4public:5void set(int y,int m,int d); // 赋值操作6bool isLeapYear(); // 判断闰年7void print(); // 输出⽇期8 };3.在类(class)中 , 成员函数及成员变量会分为两⼤类 : public members (公开成员)、private members (私有成员)1.) public members :被定义为public members 的成员函数及成员变量 , 可在任何的函数中被使⽤ .包括main函数,及其它⾮成员函数.2.) private members :被定义为private members 的成员函数及成员变量 , 只能在成员函数中被使⽤ .4.成员函数在类外部定义时,在函数名称前应加上⽇期类名前缀Date和命名空间引导符“::”,它表⽰着⾃⼰属于某⼀个名空间(类),与普通函数相区别。
1void Date::set(int y,int m,int d) { year=y; month=m; day=d; }成员函数可以在类内,也可以在类外定义,若在类内定义,则默认为内联函数(inline)5.对象是拥有操作的实体,是由类创建的6.访问成员函数的⽅式(1)对象⽅式 Date d; d.set(2011,12,5);(2)对象指针⽅式1 Date* dp = new Date;2 dp->set(2011,12,5);3// …4delete dp;7.成员函数的操作,如果只对对象进⾏读操作,则该成员函数可以设计为常对象成员函数,好处是让使⽤者⼀⽬了然的知道该成员函数不会改变对象值,同时让类的实现者更⽅便地调试。
C++课后习题答案
-3-
{ a=b=0; cout<<”Default constructor called.\n”;
} A::A(int i,int j) { a=i; b=j; cout<<”Constructor called.\n”; } void A::print() { cout<<”a=”<<a<<”,b=”<<b<<endl; } void main() { A m,n(4,8); m.print(); n.print(); } Default constructor called. Constructor called. A=0,b=0 A=4,b=8 2. #include<iostream.h> class B { public: B(); B(int i,int j); void printb( ); private: int a,b; };
-6-
5. #include<iostream.h> class Set { public:
Set(){PC=0;} Set(Set &s); void Empty() {PC=0;} int IsEmpty() {return PC= =0;} int IsMemberOf(int n); int Add(int n); void Print(); friend void reverse(Set *m); private: int elems[100]; int PC; }; int Set::IsMemberOf(int n) { for (int i=0;i<PC;i++) if(elems[i]= =n)
C++程序设计第五章
第五章特殊函数和成员5.1对象成员的初始化如果初始初始化列表某项的参数函数表为空,则列表相应的项可以省略对象成员构造函数的调用顺序取决于这些对象成员在类中的说明顺序。
析构函数的调用顺序与构造函数正好相反。
5.2静态成员简单成员函数是指声明函数不含const、volatile、static关键字的函数。
如果类的数据成员或成员函数使用关键字static进行修饰,这样的成员称为静态成员或静态成员函数,统称为静态成员。
静态数据成员能说明一次,如果在类中仅对静态数据成员进行声明,则必须在文件作用域的某个地方进行定义。
在进行初始化时,必须进行成员名限定。
除静态成员的初始化之外,静态成员遵循类的其他成员函数所遵循的访问限制,由于数据隐蔽的需要,静态数据成员通常被说明为私有的,通过成员限定访问静态成员,比使用对象名访问静态成员要好,因为静态成员是类的成员而不是对象的成员。
类中的任何成员都可以访问静态成员。
因为静态成员函数没有this指针,所以静态成员函数只能通过对象名(或指向对象的指针)访问该对象的非静态成员。
(1)可以不指向某个具体的对象,只与类名连用。
(2)在没有建立对象之前,静态成员就已经存在。
(3)静态成员为类的成员,不是对象的成员。
(4)静态成员为该类的所有对象共享,它们被存储于一个公用内存中。
(5)没有this指针,所有除非显式地吧指针传给它们,否则不能存取类的数据成员。
(6)静态成员函数不能被说明为虚函数。
(7)静态成员函数不能直接访问非静态函数。
关键字static声明的类的对象,但要注意它的构造函数与析构函数的调用特点。
5.3友员函数友员函数可以存取私有成员、公有成员和保护成员。
1.类本身的友元函数2.将成员函数做有元3.将一个类说明为另一个类的友元友元关系是不传递的即当说明类A是类B的友元,类B又是类C的友元时,5.4 const对象可以再使用const关键字定义数据成员和成员函数和修饰一个对象。
c 5第五章 静态成员,友元
35
完整版ppt
36
完整版ppt
37
完整版ppt
38
完整版ppt
39
完整版ppt
40
完整版ppt
41
完整版ppt
42
完整版ppt
43
完整版ppt
44
完整版ppt
45
完整版ppt
46
完整版ppt
47
完整版ppt
48
完整版ppt
49
完整版ppt
50
完整版ppt
51
完整版ppt
完整版ppt
1
完整版ppt
2
完整版ppt
3
完整版ppt
4
完整版ppt
5
完整版ppt
6
完整版ppt
7
完整版ppt
8
完整版ppt
9
完整版ppt
10
完整版ppt
11
完整版ppt
12
完整版ppt
Байду номын сангаас
13
完整版ppt
14
完整版ppt
15
完整版ppt
16
完整版ppt
17
完整版ppt
69
完整版ppt
70
完整版ppt
71
完整版ppt
72
完整版ppt
73
完整版ppt
74
完整版ppt
75
完整版ppt
76
完整版ppt
77
完整版ppt
78
完整版ppt
79
完整版ppt
80
此课件下载可自行编辑修改,供参考! 感谢您的支持,我们努力做得更好!
《离散数学》函数
A
B
C
y=f(x)
z =g( y ) =( g◦f )( x )
x
29
函数的复合
例
– f : → ,f (x) = x+1, – g : → ,g(x) = 2x+1, – h : → ,h(x) = x2+1, g ◦ f (x)=g(f(x)) =2f(x)+1 =2(x+1)+1=2x+3 f ◦ g(x)=f(g(x)) =g(x)+1 =2x+1+1=2x+2 h ◦ g ◦ f (x)=h(g(f(x))) = (2x+3)2+1
20
函数的性质
练习 – f: + → + , – f(1) = 1,f(n) = n–1 (n>1)
– 单射? – 满射? – 双射?
21
函数的性质
对于有限集合上的函数,有如 下主要结果:
定理 假设 A 和 B 是两个有限集合
且满足 |A| = |B|,则函数 f : AB 是单射当且仅当 f 是满射。
第五章 函数
《离散数学及应用》
第五章 函数
§5.1 函数的定义 §5.2 函数的性质 §5.3 函数的复合 §5.4 逆函数 §5.5 计算机科学中的常用函数 *§5.6 双射函数及集合的势
2
函数
A 和 B 为非空集合 设 f 为 A 到 B 的二元关系, 若对于任意 xDom( f ) 都存在唯一的 yRan( f ) 使得 (x, y)f 成立,则称 f 为函数 (function)。 函 数 也 称 作 映 射 ( mapping ) 或 变 换 (transformation)
C++对象的函数成员与全局函数
2021/6/17
12
5.1.3 函数的返回值
主调函数通过函数的调用得到一个确定 的值,称为函数的返回值。返回值是通过被调 函数中的return语句获得的。
【格式】 return <表达式> ;或 return 表达式;
或 return
【功能】将被调函数内程序的执行顺序返回给主 调函数内的调用语句,然后去执行主调函数的下 一语句。
教学内容
函数的定义与调用
内联函数
函数的重载
函数模板
变量的存储属性
2021/6/17
1
第5章 对象的函数成员与全局函数
重点、难点 函数的定义与调用 函数的递归调用(栈的应用) 函数的重载 函数模板 变量的存储属性
2021/6/17
2
第5章 对象的函数成员与全局函数
教学目标 熟练掌握函数的定义与调用 掌握函数的递归调用 掌握内联函数的概念 掌握函数的重载与函数模板的使用 掌握变量的存储属性
}
void main(){
float x,y,z;
cout<<"please input x,y=";
cin>>x>>y;
z=max(x,y)
cout<<"function main:z="<<z<<endl;
}
2021/6/17
16
5.1.4 函数调用
【格式】函数名称([实参表])
【说明】 (1)语句调用:把函数调用作为一个语句。 例如:add(x,y); (2)表达式调用:函数出现在表达式中,要求函 数带回一个确定的值参加表达式的运算。 例如:m=add(x,y); (3)参数调用:函数作为一个函数的实参参加调 用 。例如:m=max(x,max(y,z));
第五章答案类、构造函数、拷贝构造函数、静态成员、友元
5.3 练习题解答1.什么是类?为什么说类是一种抽象数据类型的实现?答:类是C++语言中的一种数据类型。
这种数据类型是一种封装体,它既包含有数据结构,又包含有对这些数据所进行的若干操作。
类的获得是通过对于所要解决的问题中的客观实体的抽象,这种抽象不仅包含了它的属性,同时还有对这些属性的操作,即方法。
对实体的这种抽象可用一个标识符来表示,并可对它引用及操作,这种标识符称为类。
可见,类是抽象数据类型的一种实现。
2.类的定义格式如何?类的说明部分和实现部分各包含些什么?答:类的定义格式包含说明部分和定义部分。
类的说明部分主要有类头和类体两部分。
类头定义格式如下所示。
class<类名>其中,class是关键字,<类名>同标识符。
类体是由一对花括号括起来的若干成员,成员中包含数据成员和成员函数,右花括号后边有一个分号。
{〈数据成员说明〉〈成员函数说明〉};成员又分为不同的访问权限,有公有(puLlic)、私有(private)和保护(protected)3种。
类的实现部分是用来定义类中说明的成员函数(没有定义)在该部分定义。
如果类中所有成员函数都已在类体内定义了,则实现部分可以省略。
3.类的成员一般分为哪两部分?这两部分有何区别?答:类的成员一般分为数据成员和成员函数两个部分。
前一部分是用来表示状态的数据,后一部分是用来改变状态的方法(即函数)。
简单地讲,前部分是变量,后部分是函数,后部分的函数是用来对前部分的变量进行操作的。
4.从访问权限角度如何区分不同种类的成员?它们各自的特点是什么?答:从访问权限角度可以将类中成员分为三种:公有的,私有的和保护的。
公有成员可以被类体内外的程序所访问,它通常作为一个类体的对外接口。
私有成员只能对类体内的程序所访问,在类体外是不可见的。
它是类中的被隐藏部分。
保护成员对一般类而言视同私有成员,对派生类同公有成员。
它可以被其派生类中的程序访问。
5.作用域运算符的功能是什么?它的使用格式如何?答:作用域运算符::是C十十语言中的一种运算符,用来指明某个标识符的作用域,主要用于标识类中成员。
课件(第5章 函数)
北京理工大学珠海学院 计算机学院 龚友明
函数的定义
设f是二元关系,如果对于任意x∈domf,都 存在唯一的y∈ranf,使得xfy成立,则称f为 函数(或者映射),这时也称y为f在x的值, 记作y=f(x) 函数相等
◦ 设f,g为函数,则
① domf=domg ② ∀x∈domf=domg,都有f(x)=g(x)
设A={1,2,3},B={a,b},求BA
解:BA={f0,f1,f2,…,f7},其中 f0={<1,a>,<2,a>,<3,a>} f1={<1,a>,<2,a>,<3,b>} f2={<1,a>,<2,b>,<3,a>} … f7={<1,b>,<2,b>,<3,b>} 说明:形如{<1,?>,<2,?>,<3,?>},每个”?”部分有n种取法,所以 有nm
f可逆。y是x的像,y=x+1. 从而x=y-1,f-1(y)=y-1
a=f-1(b)
b=f(a)
A
f-1 f 反函数
B
离散数学-第5章 函数(北理珠本末终始)
函数的复合(Compositions)
令f为从集合A到集合B的函数,g是 从集合B到集合C的函数,函数f和g 的复合用fOg表示,定义为 :(fOg)(a)=g(f(a)) 示例:
◦ 如果对任意的x1,x2∈A,x1≺x2,就有f(x1) ≺f(x2),称f为严格单调 递增。
特征函数
◦ 设A为集合,对于任意的A’⊆A,A’的特征函数χA’:A→{0,1}定 义为
番茄花园-计算机高级程序设计第五章
西南交通大学经济管理学院:何耀琴
14
(9)找到应用程序类的初始化函数 BOOL CUnModelDialogApp::InitInstance(),在初始化函 数中添加创建和显示非模态对话框的代码。(见下页图);
……//此处代码省略,下面是添加的代码
西南交通大学经济管理学院:何耀琴
15
……//此处代码省略 ……//下面方框内是添加的代码,注意添加位置
隐藏窗口,并将活动权交给其他窗体
SW_MINIMIZE
最小化窗口,并激活位于系统列表最前端的窗体
SW_RESTORE
激活并显示窗口
SW_SHOW
激活窗口,并以当前位置和大小显示
SW_SHOWMAXMIZED
激活窗口,并以最大化方式显示
SW_SHOWMINIMIZED
激活窗口,并以图标形式显示
SW_SHOWMINNOACTIVE 保持窗口的当前状态,并以图标方式显示
西南交通大学经济管理学院:何耀琴
18
GUI的组成
• 桌面:桌面是界面中最底层,有时也指包括窗口、文件浏览器在内的“桌 面环境”。在桌面上由于可以重叠显示窗口,因此可以实现多任务化。桌 面与既存的文件夹构成里面相违背,所以要以特殊位置的文件夹的参照形 式来定义内容。比如在微软公司的Windows XP系统中,各种用户的桌面 内容实际保存在系统盘(默认为C盘):\Documents and Settings\[用 户名]\桌面 文件夹里。
西南交通大学经济管理学院:何耀琴
7
西南交通大学经济管理学院:何耀琴
8
说明:成员函数DoModal() 用来生成一个模态对话框
• CPropertySheet::DoModal //所属的类 • virtual int DoModal(); //是一个虚函数
第五章总结
第五章特殊函数和成员1,成员初始化当类中定义了const成员,引用成员时,构造函数中要为这些成员初始化,使用初始化列表形式。
如:下面test类中构造函数定义形式。
PI和r是const成员和引用成员必须使用初始化列表形式,x,y是普通成员,可在函数体内为x,y赋值。
注意下面程序中PI和r的初始化形式。
2,静态成员用static声明的成员为静态成员,静态成员必须在类外初始化,静态成员不依赖于对象而存在,对象未产生之前,静态成员已存在静态成员函数没有this指针可通过类名限定来使用静态成员。
若在类体内用static声明了静态成员函数,在类体外定义静态函数时不需要加static关键字。
静态成员函数不能说明为虚函数静态成员是类的成员不是对象的成员使用时注意:类的对象可调用静态成员(数据成员和成员函数)静态成员函数不能访问非静态成员静态成员函数可访问静态成员注意:静态对象何时构造何时析构3,阅读如下程序,写出运行结果。
注意静态对象ty的生存周期:何时构造何时析构。
4,友元:普通函数作友元,类的成员函数作类的友元,一个类作另一个类的友元。
用friend声明,友元必须通过类的对象或引用来访问类中的成员。
注意:在友元函数内如(dist函数)必须通过引用来访问对象的成员。
此为类做友元友元可以访问类的私有成员,公有成员和保护成员。
友元可以是一个类或函数也可是一个类的成员函数。
友元需通过对象或引用来使用类的成员。
友元关系是单向的,A是B的友元,B不一定是A的友元。
友元关系是不传递的,A是B的友元,B是C的友元,A不一定是C的友元。
5,const对象,const数据成员,cosnt限定的函数参数,const函数1)const限定的数据成员初始化时必须使用初始化列表形式。
注意:类的数据成员在不可在定义时为数据成员初始化。
2)const变量定义时必须初始化。
注意const变量和cosnt数据成员的区别。
3)const限定的形式参数在函数体内不可出现改变参数的语句。
大连理工大学软件学院 离散数学 第五章 函数-2nd
(3) f-g: X→Y ,对每个x∈X,皆有 (f-g)(x)=f(x)-g(x),称f-g为f和g的差。 (4) f*g: X→Y ,对每个x∈X,皆有 (f*g)(x)=f(x)*g(x),称f*g为f和g的积。
11/46
特征函数
定义:设E为全集,A E,Ψ A为如下定义的从E到 {0,1}的函数:
13/46
特征函数的性质
(8) AB A B A B
x 证明:当 x A B时,AB 1,由于x A B x A, B 于是可能有这样几种情况: x a) x A 使 A 1 , B 使 B 0,于是 A B A B 1 b) x B 但x A ,此时也有 A B A B 1 c) x A 并且 x B ,此时 A B A B 1111 1 即当 x A B 时, AB A B A B
可以证明
f1 g1 f2 g1 f1 g2 I N
可见,g1和g2都是f1的右逆,而f1和f2又都是g1 的左逆。此例说明,一个函数的左逆和右逆不 一定是唯一的。
第五章成员函数
int max(int x,int y) {return(x>y?x:y);}
int min(int x,int y) {return(x<y?x:y);}
void main()
{
int a,b;
a=15,b=20;
cout<<"max="<<all(a,b,max)<<endl;
cout<<"min="<<all(a,b,min)<<endl;
> 7
<= 关系运算符
>=
X>Y X <= Y X >= Y
判断X是否大于Y 判断X是否小于等于Y
L 判断X是否大于等于Y
==
X==Y
判断X是否等于Y
8
!=
X != Y
判断X是否不等于Y
9
&
A&B
将A和B的值按位相与
10 位运算符
^
A^B
将A和B的值按位相异或
L
11
|
A|B
将A和B的值按位相或
12
&&
逻辑运算符
13
||
X<Y && X>Z X<Y || X>Z
将&&两边的结果(逻辑值)相与 L
将 || 两边的结果(逻辑值)相或
14
条件运算符
?:
Z = X>Y ? E1:E2;
如果X>Y为真,Z等于E1的值,否 则等于E2的值
R
=
X=Y
将Y的值赋给X
成员函数和友元函数
C++ Programming r.m.zhang1989@
Contents
• const Object and const Member Function • friend Function and friend Classes • Exercise
friend
Next Week
西西里相关介绍 http://soj.me/ 有关Complex类的实现(操作符重载)
You may send emails to r.m.zhang1989@ for any questions on anything puzzles you.
const 修饰函数的参数
• 对于非内部数据类型的输入参数,应该将“值传递”的方式 改为“const 引用传递”,目的是提高效率。例如将void Func(A a) 改为void Func(const A &a)。 • 对于内部数据类型的输入参数,不要将“值传递”的方式改 为“const 引用传递”。否则既达不到提高效率的目的,又降 低了函数的可理解性。例如void Func(int x) 不应该改为void Func(const int &x)。
const 成员函数
任何不会修改数据成员的函数都应该声明为const 类型。 如果在编写const 成员函数时,不慎修改了数据成员,或者调用 了其它非const 成员函数,编译器将指出错误,这无疑会提高程 序的健壮性。
const 成员函数
class Stack { public: void Push(int elem); int Pop(void); // const 成员函数 int GetCount(void) const; private: int m_num; int m_data[100]; }; } Pop(); // 编译错误,企图调用非const 函数 return m_num; int Stack::GetCount(void) const { ++ m_num; // 编译错误,企图修改数据成员m_num
C++中成员函数和友元函数的使用及区别详解
C++中成员函数和友元函数的使⽤及区别详解为什么使⽤成员函数和友元函数这个问题⾄关重要,直接影响着后⾯的理解:程序数据:数据是程序的信息,会受到程序函数的影响。
封装是⾯向对象编程中的把数据和操作数据的函数绑定在⼀起的⼀个概念,这样能避免受到外界的⼲扰和误⽤,从⽽确保了安全。
数据封装引申出了另⼀个重要的 OOP 概念,即数据隐藏。
数据封装是⼀种把数据和操作数据的函数捆绑在⼀起的机制,数据抽象是⼀种仅向⽤户暴露接⼝⽽把具体的实现细节隐藏起来的机制。
C++ 通过创建类来⽀持封装和数据隐藏(public、protected、private)。
我们已经知道,类包含私有成员(private)、保护成员(protected)和公有成员(public)成员。
默认情况下,在类中定义的所有项⽬都是私有的。
由于C++的封装和隐藏特性,只有类定义的成员函数可以访问类定义的私有数据。
成员函数是数据封装和数据隐藏的机制。
友元是C++提供的⼀种破坏数据封装和数据隐藏的机制。
成员函数的使⽤⾸先先看代码class Stock{ //class declarationprivate:std:: string company;long shares;double share_val;double total_val;void set_tot(){ total_val=shares* share_val;}public:void acquire(const std:: string & co, long n, double pr);void buy(long num, double price);void se11(long num, double price);void update(double price);void show();};//note semicolon at the end注意这⾥⾯的private可以不写,如果不写的话默认是私有的。
成员函数的说明和使用
成员函数的说明和使用Type name (Parameter)//function body留意:每一个成员函数必需返回一个值或声明返回为空(void)。
它返回类型的说明告知编译器它将返回什么类型的值。
在某些状况下,成员函数需要表示它是否胜利的完成了它的工作,此时返回类型通常为布尔型的。
参数表是用逗号分开的一组变量,它将为成员函数供应所需信息。
下面例子中定义了一个成员函数。
通过它,你的矩形类可以计算自己的面积了:int getArea(int w,int h){int a;a=w*h;return a;}另外,矩形还需要对自己进展描绘,因此它需要成员函数drawRect(),此时,你的矩形类的定义将如下所示:public class DrwRect{public static void main(String args[]) {class Rectangle{int width,height,area;public Rectangle(int w,int h){width=w;height=h;area=getArea(w,h);}protected int getArea(int w,int h) {int a;a=w*h;return a;}public void drawRect(){int i,j;for(i=width;i>0;i--)System.out.print(“#“);System.out.print(““) ;for(i=height-2;i>0;i--)System.out.print(“#“);for(j=width-2;i>0;j--)System.out.print(““);System.out.print(“#“);for(i=width;i>0;i--)System.out.print(“#“);System.out.print(““);}} //Rectangleint w=Integer.valueOf(args[0]).intValue(); int h=Integer.valueOf(args[1]).intValue(); Rectangle myrect=new Rectangle(w,h);myrect.drawRect();}}上例中最终一个“#”号后面还有一个System.out.print(““)这是由于这个成员函数在上一行没有完毕而且缓冲区没有溢出时将不把输出结果写屏。
c++函数编译原理和成员函数的实现
c++函数编译原理和成员函数的实现
c++函数编译原理是指编译器将c++源代码编译为可执行代码的过程,每个函数都有自己的编译原理。
编译原理包括从源代码到机器语言的d的过程,以及在程序空间中提供对函数的访问的过程。
c++中的函数可以分为全局函数、成员函数和静态成员函数。
成员函数是定义在特定类的作用域内的函数,它们可以访问类的所有成员变量。
而全局函数则不属于任何类,只是在全局作用域内定义的函数。
在编译过程中,全局函数和静态成员函数可以在代码段区域空间进行编译,编译完成后连接器将可执行代码放置在相应的栈上,便于在运行时调用。
而成员函数的编译原理与此有些不同。
成员函数必须附加在特定的类的内存空间,在其内存空间中只有当前类定义的所有成员函数或成员变量,所有对对象成员变量的访问都需要先对对象点号运算符引用对象,然后访问成员变量,而成员函数就是在参数表上添加一个隐藏的this指针参数,使编译器有能力访问类中定义的成员变量,调用和执行成员函数。
从以上可以看出,全局函数和静态成员函数都可以在代码段空间编译,连接器将其放置在栈上,从而在运行时可以通过普通函数的调用来访问;而成员函数则必须附加在特定的类的内存空间,且编译器必须携带this指针来访问类定义的成员变量,调用成员函数。
成员函数的特性共25页
函数级:函数的形参和在函数内定义的自动类 变量和内部静态类变量以及语句标号,这些标 识符的定义域都是在它所定义的函数体内。
块级:定义在分程序中、if语句中、switch语句 以及循环语句中的自动类和静态类变量。
类域中可以定义变量,也可以定义函数, 但定义变量不能使用auto,register和 extern等修饰符,只能用static,定义的函 数不能用extern。
文件域可以包含类域。类域介于文件类 和函数类之间。
作用域的种类
按作用域的大小可分为:
程序级:作用域最大,包含着该程序的所有文 件,程序级的有外部函数和外部变量。
友元是一种定义在类外部的普通函数,但 它需要在类体内进行说明,为了与该类的成员 函数加以区别,在说明时前面加以关键字friend。 友元不是成员函数,但是它可以访问类中的私 有成员。友元的作用在于提高程序的运行效率, 但是,它破坏了类的封装性和隐藏性,使得非 成员函数可以访问类的私有成员。
友元通俗的理解就是允许另一个类 或函数访问你的类的一种机制。友元可 以是一个函数,该函数被称为友元函数; 友元也可以是一个类,该类被称为友元 类.
友元类
友元还可以是类,即一个类可以作 为另一个类的友元。当一个类作为另一 个类的友元时,该类的所有成员函数都 是另一个类的友元函数。
整个类作为另一个类的友元: class x { friend class y; //…… };
例6-11
6.7 类的作用域
类的作用域简称类域,是指在类的定义 中由花括号括起来的部分。每个类都有 自己的类域,该类的成员局部于类所属 的域中。
构造函数调用 程序运行 对象定义处 对象定义处 创建对象处
成员运算符函数
程序运行结果如下: 2.3+4.6i 3.6+2.8i 5.9+7.4i -1.3+1.8i -4.6+29.44i 1.01731+0.486538i
从本例可以看出,对复数重载了这些运算符后, 再进行复数运算时,不再需要按照给出的表达 式进行繁琐的运算,只需像基本数椐类型的运 算一样书写即可,这样给用户带来了很大的方 便,并且很直观。
一般而言,采用成员函数重载单目运算符 时,可以采用以下两种方法来使用:
@aa;
//隐式调用
aa.operator@();
//显式调用
成员运算符函数operator@所需的一个操作数 由对象aa通过this指针隐含地传递。因此,在 它的参数表中没有参数。
说明:
(1)运算符重载函数operator@()可以返回任何类 型,甚至可以是void类型,但通常返回类型与它所操 作的类的类型相同,这样可使重载运算符用在复杂的 表达式中。例如,在例4-3中,可以将几个复数连续进 行加,减,乘,除的运算。
本 例 主 函 数 main() 中 调 用 成 员 运 算 符 ++operator++()采用了两种方式:
++ob;
与
ob.operator++();
两者是等价的,其执行结果完全相同。
从本例还可以看出,当成员函数重载单目 运算符时,没有参数被显式地传递给成员运算 符函数。参数是通过this指针隐藏地传递给函 数的。
A6=A1.operator/(A2);
由此我们可以看出,成员运算符函数 operator@实际上是由双目运算符左边的对象 A1调用的,尽管双目运算符函数的参数表只有 一个操作数是由对数A1通过this指针隐含地传 递的。以上两组语句的执行结果是完全的。
C++类的成员函数(在类外定义成员函数、inline成员函数)
C++类的成员函数(在类外定义成员函数、inline成员函数)类的成员函数(简称类函数)是函数的⼀种,它的⽤法和作⽤和前⾯介绍过的函数基本上是⼀样的,它也有返回值和函数类型,它与⼀般函数的区别只是:它是属于⼀个类的成员,出现在类体中。
它可以被指定为private(私有的)、public (公⽤的)或protected(受保护的)。
在使⽤类函数时,要注意调⽤它的权限(它能否被调⽤)以及它的作⽤域(函数能使⽤什么范围中的数据和函数)。
例如私有的成员函数只能被本类中的其它成员函数所调⽤,⽽不能被类外调⽤。
成员函数可以访问本类中任何成员(包括私有的和公⽤的),可以引⽤在本作⽤域中有效的数据。
⼀般的做法是将需要被外界调⽤的成员函数指定为public,它们是类的对外接⼝。
但应注意,并⾮要求把所有成员函数都指定为public。
有的函数并不是准备为外界调⽤的,⽽是为本类中的成员函数所调⽤的,就应该将它们指定为private。
这种函数的作⽤是⽀持其它函数的操作,是类中其它成员的⼯具函数(utility function),类外⽤户不能调⽤这些私有的⼯具函数。
类的成员函数是类体中⼗分重要的部分。
如果⼀个类中不包含成员函数,就等同于C语⾔中的结构体了,体现不出类在⾯向对象程序设计中的作⽤。
在类外定义成员函数在前⾯已经看到成员函数是在类体中定义的。
也可以在类体中只写成员函数的声明,⽽在类的外⾯进⾏函数定义。
如:class Student{public :void display( ); //公⽤成员函数原型声明private :int num;string name;char sex;//以上3⾏是私有数据成员};void Student::display( )//在类外定义display类函数{cout<<"num:"<<num<<endl;cout<<"name:"<<name<<endl;cout<<"sex:"<<sex<<endl;}Student stud1,stud2; //定义两个类对象注意:在类体中直接定义函数时,不需要在函数名前⾯加上类名,因为函数属于哪⼀个类是不⾔⽽喻的。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
面向对象程序设计 第二版
流程图表示法: 流程图就是用一些图框 表示各种操作。用流程图来 表示算法最大的优点就是直 观形象,便于理解,并且实 用性强,能够方便的表示包 含分支和循环的结构,避免 了用自然语言表示算法的不 足。
开始
1 => i
2 => n
n × i => n
i + 1 => i
N
i>5 Y 结束
面向对象程序设计 第二版
但是这些函数名各不相同,无法向使用者提供一个统一的
接口,为了达到这个目的,我们可以采用回调函数机制:
void Sum(void* operand1, void* operand2, void* result, void(*pSum )(void*, void*, void*))
返回值类型 (*函数指针名)(参数表);
例如:int ( * func_p)(char a , char b);
其中,“int‖表示函数的返回值类型为整型, “(*func_p)‖表示func_p是一个指针,后面的(char a, char b)表示该指针(func_p)是函数指针。其定义后 产生的指针变量有全局、静态与局部之分,同样占有
因此,这种方法一般被专业的软件开发人员采用, 特别是在详细设计中采用伪代码表示法,可以使以后的 编码阶段变得简单。
面向对象程序设计 第二版
计算机语言表示法:
一个算法要拿到计算机上去运行,最终还是 得采用计算机语言表示。计算机是无法识别流程图 和伪代码的。只有严格按照计算机语言语法编写的 程序才能被计算机执行。目前使用的计算机语言多 种多样,本书所介绍的面向对象的程序设计语言
面向对象程序设计 第二版
5.3.2 成员函数的调用
一般形式有两种:
对象名.函数名(实参1,实参2,…); 对象指针→函数名(实参1,实参2,…);
例如:
void main() { ┇ cout << ―The area of circle = ‖ << mycircle.circle_area(3.14); ┇ }
面向对象程序设计 第二版
通过函数指针调用上述函数
int Caller(const char* string, int(*f_p)(const char*))
// ↑通过形参的形式,说明一个函数指针int(*f_p)(const char*) { return (*f_p)(string); //通过参数结合的形式将函数 //指针指向被调用的函数int len(const char* string) }
面向对象程序设计 第二版
说明一个函数原型的一般形式有两种:
函数返回值类型 函数名(参数类型1 参数名1, 参数类型
2 参数名2, …);
函数返回值类型 函数名(参数类型1, 参数类型2 , …);
以上两种方法均可以使用,但是为了增加程序
的可读性建议使用第一种方法。
成员函数的定义: (1)对于代码较少的成员函数的定义,可以直接在类中进行。 class Circle { protected: int Radius; … public: fioat circle_area(fioat pi){return pi*Radius*Radius;} … }; (2)对于代码较多的成员函数的定义,通常只在类中进行原型说明,在类外对 成员函数进行定义。 class Circle float Circle::circle_area(float pi) { { protected: return pi*Radius*Radius; int Radius; } … public: fioat circle_area(fioat pi); … 请注意,这时的函数名应该包含: }; 类名(Circle)+ 作用域分辨符(::)+ 原函数(circle_area)
在程序运行中,每个函数在编译时都会被编译
器分配给一个入口地址,则指向这个入口地址的 指针就称为函数指针。函数代码是程序的算法指 令部分,被存放在代码区(code),函数指针指
向代码区中某个函数的地址,因此,通过函数指
针可以调用相应的函数。
面向对象程序设计 第二版
⑴函数指针的声明
正确的指针类型声明如下:
// 这里pSum就是一个指向回调函数的指针。
// 定义统一接口:
void Sum(void* operand1, void* operand2, void* result, void(*pSum )(void*, void*, void*))
{
(*pSum)(operand1, operand2, result);
一个完整的算法应该具有以下5个特性:
有穷性、确定性、有效性、输入性和输出性。
面向对象程序设计 第二版
5.2.2 算法的表示
为了表示一个算法,可以采用多种形式。 最常见的几种方法有自然语言表示法、流程图 表示法、伪代码表示法和计算机语言表示法。 自然语言表示法: 自然语言表示法就是用我们日常生活中的语 言来表示算法的实现过程,对采用何种语言没 有限制。但是采用自然语言表示往往不太严格, 容易造成歧义。另外,用这种方法描述包含分 支和循环的算法不太方便。因此,自然语言表 示法很少用来描述复杂的算法。
为了实现对象的行为,我们把一些相关的语句
组织在一起,并给它们注明相应的名称,形成一
些相对独立而且便于管理和阅读的小块程序,每
个小程序块描述了一个完整的行为,这种形式的
组合就构成了成员函数。
面向对象程序设计 第二版
5.2 算法描述 5.2.1 算法的概念
一个完整的对象应该包括两个方面的内容,
即对数据的描述(对象属性)和对操作的描述 (对象行为)。对操作的描述也就是算法,是设 计和实现对象行为的灵魂。
面向对象程序设计 第二版
回调函数
简单来说,回调函数就是指通过函数指针调用的函数。 当你把函数指针作为参数传递给另一个函数,另一个函数通 过该指针调用该函数,我们就称被调用的这个函数为一个回 调函数。 如下所示:
void CallBack(char a){…} // 准备作为回调函数的函数 int ( * func_p)(char a ); // 指向回调函数的指针 func_p = CallBack; // 将函数指针指向回调函数 void fun(int x, int ( * f_p)(char a )){(*f_p)(―hello‖); …} // 准备使用回调函数的函数 fun(5, func_p); // 使用回调函数,我们通过函数指针 // 隐式的调用了回调函数void //CallBack(char a)
面向对象程序设计 第二版
回调函数可以消除调用者和被调用者之间的耦合性。 调用者不用关心需要调用哪个函数,它所需要知道的仅 仅是函数原型。让我们通过一个例子来体会回调函数的 威力。假设我们开发了若干个函数用来求两数之和, 这些函数针对不同的数据类型:
void SumForInt (int* oper1, int* oper2, int* result) { *result = *oper1 + *oper2; } void SumForFloat (float* oper1, float* oper2, float* result) { *result = *oper1 + *oper2; } void SumForDouble (double* oper1, double* oper2, double* result) { *result = *oper1 + *oper2; }
图5.1 一般流程图表示算法 面向对象程序设计 第二版1 => i 2 => n n × i => n i + 1 => i 直到 i > 5 打印 n
图5.2 N-S流程图表示算法
面向对象程序设计 第二版
伪代码表示法:
伪代码是用介于自然语言和计算机语言之间的文字 和符号来描述算法。从结构上看,伪代码表示法类似于 最终的计算机语言,每一行就表示一个基本的操作。它 不用图形符号,因此书写方便、格式紧凑,也易于理解, 便于向最终的程序过渡。伪代码表示法书写格式比较自 由,容易直观表达出设计者的思想。同时,书写的算法 也容易修改,很容易写出结构化的算法。
面向对象程序设计 第二版
⑵函数指针可以作为函数的参数,如下所示: 编写一个函数,计算一个字符串的长度 int len(const char* string) { const char* p = string; for(int i = 0; *p != ‗\0‘; i++) { p++; } return i; }
内存空间(与其他类型指针变量所占空间相同)。
面向对象程序设计 第二版
由于(*func_p)所扮演的角色与函数名相同,因此在使 用(*func_p)时,只需将他看作函数名即可。 请看下面一个例子,学习如何通过函数指针调用函数: int func(int); int (*func_p)(int); func_p=func; //↑函数指针(*func_p)指向代码区函数func()的地址 int x = func (4);//使用函数func(),这个用法很常见 int y = (*func_p)(5); //↑使用函数指针(*func_p)实际上调用了func()函数
面向对象程序设计 第二版
第五章 成员函数
5.1 成员函数的概念 5.2 算法描述 5.3 成员函数的定义与调用 5.4 运算符和表达式 5.5 控制结构 5.6 函数参数的传递机制 5.7 函数的参数 5.8 静态成员函数 5.9 函数的重载 5.10 两种特殊函数 小结
面向对象程序设计 第二版
5.1 成员函数的概念