C++程序设计课件 设计制作:徐龙琴 2
教学内容:
11.1 类 的概念及定义
11.2 对象 的概念、定义及初始化
11.3类 和 对象 的 作用域
11.4 const成员函数
11.5 静态成员
11.6 友元 及 友元类
C++程序设计课件 设计制作:徐龙琴 3
?掌握 类 的 概念, 定义格式,类与结构的关系
?掌握 对象 的 定义
?掌握 构造函数 和 析构函数 的含义与 作用, 定义方式
和实现
?掌握 友元函数 的 含义,友元函数和成员函数的区别
教学目的:
C++程序设计课件 设计制作:徐龙琴 4
§ 11.1 类的概念及定义
随着软件业的发展,出现了需要多人合作方能完成的大
型软件,而 结构化程序设计方法 是一种面向数据或面向过程的
设计方法,它 将 数据和对数据的处理过程分开,给 软件的 调试,
维护带来了很大困难 。 为了 解决这些问题,人们 提出了 面向对
象的程序设计 (00P)。
00P是把 程序 构造成 由 若干 对象组成, 每个对象 由 一些
数据以及对这些数据所实施的操作构成 ; 对象间通过消息 (调
用对象的操作 )相互联系 ; 将有共同属性和行为的一批对象抽
象成 类 。 一个类所描述的属性可以从其它的类继承。
C++程序设计课件 设计制作:徐龙琴 5
C++的类 是在 结构体 的基础 上扩充而来的 。 类是 把各种 不
同类型的数据 ( 称为数据成员 ) 和 对数据的操作 ( 成员函数 )
组织在一起而形成的 用户自定义的数据类型 。
C++中, 类 定义包括 类说明 和 类实现 两大部分 。 说明部
分提供了 对该类所有数据成员和成员函数的描述, 而 实现部分
提供了 所有成员函数的实现代码 。
⒈ 类的概念
C++程序设计课件 设计制作:徐龙琴 6
class 类名
{
private:
私有数据成员或成员函数;
protected:
保护数据成员或成员函数;
public:
公有数据成员或成员函数;
};
各个成员函数的定义;
⒉ 定义类的一般形式为:
类型 类名,,函数名(参数表) //各成员函数的定义
{
函数体
}
:,称为 作用域运算符,指明该
成员函数是属于哪个类的
C++程序设计课件 设计制作:徐龙琴 7
定义类的说明:
class是 定义类的关键字,类名是 一个标识符,用于惟一标
识一个类,一般 首字母大写
大括号内是类体 (包含数据成员和函数成员),类的成员
从 访问权限 上分有以下三类:
public,该成员 可以被程序中的任何代码访问 ;
private,只能被 类本身成员函数 及 友元类的成员函数 访问
protected,只能被 类本身的成员函数, 友元类的成员函数
和 该类的派生类 的成员访问。
类的成员从访问权限 默认为 private权限
成员函数可以 在类体中定义, 也可 在 类体外定义,在类体
外定义成员函数时,必须先在类体中作函数的原型说明
C++程序设计课件 设计制作:徐龙琴 8
类的数据成员 描述了 类的属性,类的成员函数 反映了 对
数据成员的操作, 也 可 称 为, 方法, 。 成员函数可以重载
允许声明 重载函数 和 带缺省形参值的函数
类是一种自定义的数据类型,系统并不为类分配存储空间 。
类名不能与变量同名。
为了提高运行时的效率,对于简单的函数 可以声明为内联形
式 (函数体放在类的声明中或使用 inline关键字)
类体中 不允许对数据成员进行初始化 。
类中的 数据成员的类型 可以是任意,可以 是 另一个类的对象,
但 自身类的对象是不可以的 。
C++程序设计课件 设计制作:徐龙琴 9
class Record
{ private:
char bookname[20]; //数据成员 bookname(用于表图书名称 )
int number; //数据成员 number,表示图书编号
public,//public成员
void regist(char *a,int b); //成员函数 regist,用于给
//各数据成员赋值
void show(); //成员函数 show,显示各数据成员的值
};
void Record::regist(char *a,int b)
{ … }
void Record:,show( )
{ … }
例,描述 图书的类定义
C++程序设计课件 设计制作:徐龙琴 10
⑴ 类 成员函数的定义,
① 将成员函数的定义直接写在类中,
class Record
{ private:
char bookname[20];
int number; //数据成员 number,表示图书编号
public:
void regist(char *a,int b) //成员函数 regist()的定义
{ strcpy(bookname,a); //给数据成员 bookname赋值
number=b; //给数据成员 number赋值
}
void show() //成员函数 show()的定义
{ cout<<”名称:, <<bookname<<endl;
cout<<”号码:, <<number<<endl; }
};
在类中直接定义成员函数的情况 一般适合于 成员 函数规模较
小的情况,也就是说它们一般为内联函数,即使没有明确用
inline关键字。
C++程序设计课件 设计制作:徐龙琴 11
② 成员函数的定义写在类的定义之后,
class Record
{ private:
char bookname[20];
int number; //数据成员 number,表示图书编号
public:
void regist(char *a,int b) ;
void show() ;
};
void Record:,regist(char *a,int b)
{ strcpy(bookname,a); //给数据成员 bookname赋值
number=b; //给数据成员 number赋值
}
void Record:,show( )
{ cout<<”名称:, <<bookname<<endl;
cout<<”号码:, <<number<<endl; }
通常将类 的 定义写在 一个头文件(,h文件)中, 成员
函数的定义 写在 一个程序文件(,cpp文件)中,这样,就相
当于把 类的定义 (头文件) 看成是 类的外部接口, 类的成员
函数的定义 看成 类的内部实现 。
C++程序设计课件 设计制作:徐龙琴 12
⒊ 类与 结构,
结构是类的一种特例,在结构中也可以定义成员函数。
定义结构时只要把关键字 class 改为 struct即可。 结构和类
的唯一区别是,在未指定访问权限时,结构中的成员被默认
为公有的而类中的成员被默认为私有的。 在所有其他方面,
类和结构等价 。 尽管类和结构是等价的,但 一般在描述数据
时使用结构,在描述数据及对数据的操作时 用类 。
C++程序设计课件 设计制作:徐龙琴 13
include <iostream.h>
class Sample
{ int x,y;
public:
Sample( ) {x=y=0;}
Sample (int a,int b) {x=a;y=b;}
void disp( )
{ cout<<”x=”<<x<<”,y=”<<y<<endl;}
};
void main()
{Sample s1,s2(1,2);
s1.disp( );
s2.disp( ); }
例:
运行结果为:
x=0,y=0
x=1,y=2
C++程序设计课件 设计制作:徐龙琴 14
§ 11.2 对象的概念及定义
对象 是 类的 一个具体实现,被称为 实例,任何一个对象都是
属于某个已知类的 。因此在 定义对象之前必须先定义类 。 定义 一
个 类后, 便可以如同声明简单变量一样创建对象。
⒈ 定义对象的 3种格式,
⑴ 在定义类的同时定义对象
例,class sample
{ int i;
void set(int y)
{ i=y; }
int geti()
{ return i; }
}data1,data2; //定义两个 sample型的对象 data1,data2
C++程序设计课件 设计制作:徐龙琴 15
⑵ 在定义类的同时定义对象
例,class
{ int i;
void set(int y)
{ i=y; }
int geti()
{ return i; }
}data1,data2; //定义两个对象 data1,data2
C++程序设计课件 设计制作:徐龙琴 16
⑶ 先定义类,再定义对象
例,class sample
{ int i;
void set(int y)
{ i=y; }
int geti()
{ return i; }
};
sample data1,data2; //定义两个 sample型的对象 data1,data2
C++程序设计课件 设计制作:徐龙琴 17
2 对象成员的表示方法:
对象成员 就是 该类所定义的成员,分为 数据成员和函数
成员。其 表示方法分为 通过 对象访问成员 和通过 类指针访问
成员 两种形式:
① 通过对象访问成员的格式:
对象名,数据 成员名
或
对象名,函数 成员名(参数表)
注意:,,”是一个运算符,该运算符的功能是表示对象的成员
C++程序设计课件 设计制作:徐龙琴 18
② 通过 指向对象的指针访问的格式,
对象指针名 ->数据成员名
或
对象指针名 ->函数成员名 ( 参数表 )
注意:, ->”,表示成员的运算符。它与,,”的区别是:, -
>”
用来 表示 指向对象的指针的成员,而,,”用来 表示 一
般
对象的成员。
( *对象指针名),数据成员名
C++程序设计课件 设计制作:徐龙琴 19
#include<iostream.h>
class Score
{ private:
float average;
public:
void newscore(float avg)
{ average=avg;}
void printscore( )
{ cout<<"平均分,"<<average<<endl;}
};
void main( )
{ Score stud1,stud2;
stud1.newscore(85);
stud2.newscore(92);
cout<<“学生一 的 "; stud1.printscore( );
cout<<“学生二 的, ; stud2.printscore( );
}
例, 给出下列程序的输出结果
注意,对类的私有成员,只能通过其成员函数来访问,不能
在类外对私有成员访问。
stud1,average=85; //error
运行结果为:
学生一 的 平均分, 85
学生 二的 平均分, 92
C++程序设计课件 设计制作:徐龙琴 20
⒊ 对象的初始化:
可用 构造函数 (它是类中特殊的成员函数 )来 给对象初始化
也可用 析构函数 来 释放一个对象 。
⑴ 构造函数:
① 作用,为对象分配空间;对其数据成员赋初值。
② 特点,
创建对象时,系统自动调用 构造函数
是特殊的 公有 成员函数,其 函数名 与 类名相同 且 可有 任
意类型的 参数,但 不能有 返回类型 。
一个 类可以 拥 多个构造函数 (重载),若类没给出构造
函数则编译器会自动给出一个 不带参数 的 默认构造函数
构造函数 可 以 在类体中定义, 也可以 在类体外定义
C++程序设计课件 设计制作:徐龙琴 21
#include <iostream.h>
class sample
{ char ch; int i; float f;
public,
sample( ) {ch='A';i=1;f=0.0;} //不带参数的 构造函数
sample(char,int,float); //重载构造函数
void show();
};
sample::sample(char nch,int a,float b) //构造函数的定义
{ ch=nch; i=a; f=b; } //初始化三个数据成员
void sample::show()
{cout<<"output:"<<ch<<" "<<i<<" "<<f<<endl; }
void main( )
{ sample obj1; //创建对象 obj1时,自动调用缺省构造函数
obj1.show(); //调用成员函数 print
sample obj2(?B?,10,8.9); //自动调用重载构造函数初始化对象 obj2
obj2.show(); }
例, 构造函数 举例
运行结果为:
output,A 1 0
output,B 10 8.9
C++程序设计课件 设计制作:徐龙琴 22
#include <iostream.h>
class sample
{ int i,j;
public,
sample(int ti,int tj)
{ i=ti; j=tj; }
void print()
{ cout<<i<<'\t'<<j;}
};
void main()
{ sample te; //编译时出错,没有无参的构造函数。
sample temp(3); //编译时出错,没有合适的构造函数
}
例, 构造函数的调用 举例
C++程序设计课件 设计制作:徐龙琴 23
#include <iostream.h>
class example
{ int i,j;
public,
example( )
{ i=10;j=20; }
example(int ti=30,int tj=40) //缺省构造函数
{ i=ti; j=tj; }
void print()
{ cout<<i<<'\t'<<j<<endl; }
};
void main()
{ example te;
example temp(50);
temp.print(); }
例, 缺省构造函数 举例
//产生二义性,无法确定自动调用哪个构造注意,在用 默认构造函数创建对象 时,如果创建的是 全局对象
或静态对象,则 对象的默认值为 0,否则对象的初始值是
不定的 。 构造函数有缺省参数时,称为 具有缺省构造函
数
C++程序设计课件 设计制作:徐龙琴 24
⑵ 析构函数:
① 作用,进行清除对象,释放内存
② 特点,
当对象生命期结束时,系统自动调用 类的析构函数
对象被 析构的顺序 与 对象建立时的顺序 正好 相反
析构函数 为,~类名 ( ) { };它 没 有 参数 和 返回类型
一个类中 只能 定义 一个 析构函数,故析构函数不能重载。
若类中 没 定义 析构函数, 编译器会自动生成 一个默认析
构函数 (它是一个空函数 )
析构函数可以被调用,也可以 被系统自动调用 (当 对象
定义在函数体内时,该对象的析构函数会被自动调用;
当 一个对象是使用 new动态创建的,在使用 delete运算
符释 放它时,delete也将会自动调用析构函数。
C++程序设计课件 设计制作:徐龙琴 25
# include <iostream.h>
# include <string.h>
class Teacher
{ private:
char * name; int age;
public:
Teacher(char *i,int a )
{ name=new char[strlen(i)+1] ;
strcpy (name,i);
age = a;
cout << "\n执行构造函数 Teacher "<< endl; };
~ Teacher ( )
{ delete[] name ;
cout << "执行析构函数 ~Teacher "<< endl;} ;
void show();
};
void Teacher,,show ()
{ cout << "姓名,"<<name<<" "<<"年龄,"<<age<< endl; }
void main()
{ Teacher obj ("张立三 ",25);
obj.show(); }
例, 析构函数 举例
运行结果为:
执行构造函数 Teacher
姓名:张立三 年龄,25
执行析构函数 ~Teacher
C++程序设计课件 设计制作:徐龙琴 26
//t.h
class TDate1
{ public,
TDate1(int y,int m,int d);
~TDate1( );
void Print( );
private,
int year,month,day;
};
TDate1::TDate1(int y,int m,int d)
{ year=y; month=m;day=d;
cout<<"Constructor called.\n";
}
TDate1::~TDate1( )
{ cout<<"Destructor called.\n";}
void TDate1::Print( )
{ cout<<year<<"."<<month<<"."<<day<<endl;}
例, 构造函数和析构函数 举例
#include<iostream.h>
#include"t.h"
void main( )
{ TDate1 today(2004,3,5);
TDate1 tomorrow(2004,3,6);
cout<<"today is ";
today.Print( );
cout<<"tomorrow is ";
tomorrow.Print( );
}
运行结果为:
Constructor Called,
Constructor Called,
today is 2004.3.5
tomorrow is 2004.3.6
Destructor called,
Destructor called.
C++程序设计课件 设计制作:徐龙琴 27
⑶ 拷贝构造函数,
拷贝构造函数 是 C++中引入的一种 新的构造函数 。
定义 一个 拷贝构造函数的方式 是:
类名 ( const 类名 &形式参数 )
{ 函数体 }
由此可看出:
( 1) 拷贝构造函数的 名称 与类名相同, 且 只有 一个参数,
该 参数就是 对 该类对象的引用 。
( 2) 拷贝构造函数的 功能是 用于实现对象值的拷贝, 通过
将一个同类对象的值拷贝给一个新对象, 来完成对新对
象的初始化, 即用一个对象去构造另外一个对象 。
C++程序设计课件 设计制作:徐龙琴 28
#include <iostream.h>
class Example
{ private:
int num;
char *name;
public:
Example(int i,char *str )
{ name=str; num=i; }
Example(const Example &x)
{ num=x.num; }
void list()
{ cout<<"\n数据成员 num的值 ="<<num<<endl; }
};
void main()
{ Example obj1(215,"张立三 ");
Example obj2(obj1);
obj2.list();
}
例,拷贝 构造函数 举例
运行结果为:
数据成员 num的值 =215
注意,若类中没有定义拷贝构造函数,则 编译器产生一个缺省
的拷贝构造函数,以实现对象的属性复制
C++程序设计课件 设计制作:徐龙琴 29
#include <iostream.h>
class FUNA
{ int x;
public,
FUNA (int tx)
{ x=tx;
cout<<"call the constructor function FUNA!\n";}
void print()
{ cout<<x<<"\n";}
~ FUNA ()
{ cout <<"call the destructor function FUNA!\n";}
};
例, 将一个已定义类的对象作为该类的成员 的例子
C++程序设计课件 设计制作:徐龙琴 30
class FUNB
{ int y;
public,
FUNB (int ty)
{ y=ty;
cout<<"call the constructor function FUNB!\n";}
void print()
{ cout<<y<<"\n";}
~ FUNB ()
{ cout <<"call the destructor function FUNB!\n";}
};
C++程序设计课件 设计制作:徐龙琴 31
class FUNC
{ int z;
FUNA showa;
FUNB showb;
public,
FUNC(int tz,int tx,int ty);
void show()
{ cout <<z<<"\n"; showa.print(); showb.print();}
~ FUNC()
{ cout<<"call the desturctor function FUNC!\n"; }
};
FUNC:,FUNC (int tz,int tx,int ty):showb(ty),showa(tx)
{ z=tz; cout<<"call the constructor function FUNC!\n";}
void main()
{ FUNC showc (10,20,30);
showc.show();
}
运行结果为:
call the constructor function FUNA!
call the constructor function FUNB!
call the constructor function FUNC!
10
20
30
call the constructor function FUNC!
call the constructor function FUNB!
call th cons ructor function FUNA!
注意,对象成员的 构造函数的调用顺序 取决于 这些对象在类
FUNC中的 说明顺序, 与它们在类 FUNC的构造函数
定义中的顺序无关。
C++程序设计课件 设计制作:徐龙琴 32
§ 11.3 类和对象的作用域
在定义类时,类中说明的标识符仅在该类有效。
例,#include <iostream.h>
class rectangle
{ int length,width; //length是 rectangle的属性
…
};
length=50; //此处的 length表示的是程序的一个全局
void main()
{ …
}
C++程序设计课件 设计制作:徐龙琴 33
总之,① 类的类型名的作用域,与普通标识符的作用域相同,
即在函数外定义的类,其类名作用域为 文件作用域 ;
且类的作用域中说明的标识符仅在该类有效。在函
数内定义的类,其类名作用域为 块作用域 。
② 对象作用域 与变量作用域相同 。
C++程序设计课件 设计制作:徐龙琴 34
③ 类的成员函数 能访问 类的私有成员, 对象或指向对象的指针
只能访问 类的公有成员 。
④ 类 一般定义在 全局的作用域中, 也可定义在 局部作用域 (即
函数中)中,但很少。
⑤ 类 也 可定义在另一个类中, 称为嵌套类 。
C++程序设计课件 设计制作:徐龙琴 35
int fork (void); // 全局 fork
class Process
{
int fork (void);
...
};
int Process::fork (void)
{
int pid =,:fork(); // 访问 全局 函数 fork
...
}
例, 类的作用域
C++程序设计课件 设计制作:徐龙琴 36
#include<iostream.h>
class a
{ int x;
public,
void initial(int y)
{ x=y; }
void print()
{ cout<<x<<'\t'; }
};
a s;
void main()
{ s.initial(5);
s.print();
a temp;
temp.initial(12);
temp.print();
cout<<endl; }
例, 类名作用域与对象作用域
运行结果为:
5 12
C++程序设计课件 设计制作:徐龙琴 37
§ 11.4 const成员函数
在定义的类的成员函数中,常常有一些 成员函数 不改变 类
的数据成员,也就是说,这些函数 是, 只读, 函数,而 有一些
函数 要 修改 类数据成员的值 。 如果把不改变数据成员的函数都
加上 const关键字 进行标识,这样不仅 可提高程序的可读性,
还能提高 程序的可靠性,已定义成 const的成员函数,一旦企
图修改数据成员的值,则编译器按错误处理。
类型 函数名 (参数表 ) const;
⒈ 常成员函数说明格式如下:
C++程序设计课件 设计制作:徐龙琴 38
对于 const成员函数 需要 注意以下几点:
( 1) const是函数类型的一个组成部分, 因此在 实现部分也
要带 const关键词 。
( 2) 常成员函数 不更新 对象的数据成员, 也 不能 调用该类中
没有用 const修饰的成员函数 。
( 3) 如果将一个对象说明为 常对象, 则通过该常对象 只能调
用它的常成员函数, 而不能调用其他成员函数 。 但 构造
函数和析构函数 例外, 定义 它们从 不加 const,但它们
能被 const对象调用 。
( 4) const关键词 可以参与 区分重载函数 。 例如, 如果在类
中有说明:
void print( );
void print( ) const;
则这是对 print的有效重载。
C++程序设计课件 设计制作:徐龙琴 39
⒉ 常数据成员格式如下:
就像一般数据一样,类的成员数据也可以是常量和常
引用,使用 const说明的数据成员 称为常数据成员 。如果在
一个 类中说明了常数据成员,那么 构造函数就只能通过初
始化列表对该数据成员进行初始化。
#include <iostream.h>class FUNC
{ int z; const int x;
const char y; public,
FUNC(int tz ):x(10),y('a'){ z=tz; cout<<"The constructor called!\n";}
void display(){cout<<z<<" " <<x << " " <<y;} };
void main(){ FUNC d(20);
d.display();}
例:
运行结果为:
The constructor called!
20 10 a
C++程序设计课件 设计制作:徐龙琴 40
§ 11.5 静态成员
静态成员 的 特性是 不管这个类创建了多少个对象,其静态
成员 只有一个拷贝 (副本),这个副本被所有 属于这个类的对象
共享 。静态成员 声明 以关键字 static开始,包括 静态数据成员和
静态成员函数。
1 静态数据成员,
⑵ 初始化格式, 数据类型 类名,:静态数据成员名 =值
⑶ 访问静态数据成员格式, 类名,:静态数据成员名
static 数据类型 数据成员名⑴ 定义格式,
C++程序设计课件 设计制作:徐龙琴 41
注意:① 静态数据成员 可 定义为 公有 或 私有的,但它 是类所有
对象 共享的
② 它具有静态生存期,故 必须 在类 和所有的成员函数之 外
初始化 (可在 main函数前或中初始化 )。
③其在 初始化时前面不加 static关键字
④在 初始化或访问时 必须 用 (::)指出它所属的类
⑤静态数据成员 在每个类对象中 并 不占有存储空间, 它仅
在 初始化时分配内存 且 仅 创建和初始化一次
⑥ 公有的静态数据 成员 可 以 直接访问, 但私有的 或保护的
静态数据成员 必须通过静态成员函数 进行 访问
C++程序设计课件 设计制作:徐龙琴 42
#include<iostream.h>
class Myclass
{ public,
Myclass(int a,int b,int c);
void GetNumber( );
void GetSum( );
private,
int A,B,C;
static int Sum; };
int Myclass::Sum=0; //静态变量初始化
Myclass::Myclass(int a,int b,int c)
{ A=a;B=b;C=c; Sum+=A+B+C;}
void Myclass::GetNumber( )
{ cout<<"Number="<<A<<","<<B<<","<<C<<endl;}
void Myclass::GetSum( ) { cout<<"Sum="<<Sum<<endl; }
void main( )
{ Myclass M(1,2,3),N(4,5,6);
M.GetNumber( );
N.GetNumber( );
M.GetSum( );
N.GetSum( ); }
例,静态成员举例
运行结果为:
Number=1,2,3
Number=4,5,6
Sum=21
Sum=21
C++程序设计课件 设计制作:徐龙琴 43
2 静态成员函数,
⑵ 访问静态成员函数格式, 类名,:静态成员函数名 (参数表 )
static 函数类型 函数名 (参数表 ) ⑴ 定义格式,
注意:① 静态成员函数 不能直接引用 类中的 非静态成员,可以
引用类中说明的静态成员。但静态成员函数 可通过
对象来引用非静态成员 。
②静态成员函数也 属于整个类 而 不属于类中的某个对
象,它是该类的所有对象共享的成员函数
③ 静态成员函数 可在类体内定义,也可以在 类外定义
C++程序设计课件 设计制作:徐龙琴 44
#include <iostream.h>
class gate
{ int input1,input2,output;
static int count; //定义一个静态变量
public,
gate( )
{ input1=0;input2=0;output=0;count++; }
static void display(gate first) //定义一个静态成员函数
{ cout << count << endl;}
};
int gate::count=0; //分配内存空间
void main( )
{ gate first,second;
cout << "eof objects created,";
gate::display(first); //调用静态成员函数
gate::display(second); //调用静态成员函数
}
例,静态成员函数举例
运行结果为:
eof objects created,2
2
C++程序设计课件 设计制作:徐龙琴 45
#include<iostream.h>
class M
{ public,
M(int a)
{ A=a; B+=a; }
static void f1(M m); //定义静态函数 f1()
private,
int A;
static int B;
};
void M::f1(M m)
{ cout<<“A=”<<m.A<<endl; //调用一个非静态变量
cout<<“B=”<<B<<endl; //调用一个静态变量 }
int M::B=0;
void main( )
{ M P(5),Q(10);
M::f1(P); //调用静态函数,P是 M类的对象
M::f1(Q);
}
例,静态成员函数举例
运行结果为:
A=5
B=15
A=10
B=15
C++程序设计课件 设计制作:徐龙琴 46
§ 11.6 友元函数和友元类
友元 提供了 不同类成员函数之间、类的成员函数与一般函
数之间进行 数据共享的机制 。对于一个类,可 用 关键字 friend
将 一般 函数,其他类的成员函数或其他 类声明为 该类的友元,
使得这个类中本来隐藏的信息(包括私有成员和保护成员)可
以被友元所访问。
若友元是函数,则 称为 友元函数 ;若友元是一个类,则
称为 友元类,友元类的所有成员函数都成为该类的友元函数。
C++程序设计课件 设计制作:徐龙琴 47
1 友元函数
⑴ 引入原因, 为了 让非成员函数访问类中私有成员,以便提高
程序运行效率,便提出了友元方案。但是,友元
函数的使用 会破坏 类的封装性与隐藏性,应尽量
慎用
⑵ 友元函数的特点:
① 非 成员函数,但 可访问 类中的所有成员
② 在类体内 以 friend开头加以声明 (该声明可放在公有部分,
也可放在私有部分 )。友元函数的定义可在类的内部或外部
③友元函数 不可继承
④ 友元函数的 使用同普通函数一样
C++程序设计课件 设计制作:徐龙琴 48
⑶ 使用友元函数的情况如下:
① 运用运算符重载
② 创建一定 I/O函数
③ 一个函数需要访问一个或多个不同类的私有成员。
C++程序设计课件 设计制作:徐龙琴 49
#include <iostream.h>
class rectangle
{ int length; int width;
public,
friend int area(rectangle); //友元函数的原型说明
void setdata(int,int);
};
int area(rectangle temp) //友元函数的定义如普通函数
{ int tarea=temp.length*temp.width;
return tarea; }
void rectangle::setdata(int i,int j)
{ length=i; width=j; }
void main( )
{ rectangle a;
a.setdata(6,12);
cout<<area(a)<<“\n”; //友元函数的调用犹如变通函数
}
例,友元函数举例
运行结果为:
72
C++程序设计课件 设计制作:徐龙琴 50
#include <iostream.h>
class Circle; //提前说明,告诉编译器 Circle 是什么意思。
class Rectangle
{ float width;
float length;
float area;
public,
Rectangle(float w,float l) //构造函数,初始化数据成员
{width=w; length=l; area=w*l; }
friend float gr_area(Circle c,Rectangle r);
};
class Circle
{ float radius,area;
public,
Circle(float r) //构造函数,初始化数据成员
{ radius=r; area=3.14*radius*radius; }
friend float gr_area(Circle c,Rectangle r);
};
例, 通常一个友元函数在一个或多个类内
C++程序设计课件 设计制作:徐龙琴 51
float gr_area(Circle c,Rectangle r)
{ return c.area-r.area; } //访问两个不同类中的私有成员
void main()
{ float x;
Circle c1(3.3);
Rectangle r1(3.3,2.2);
x=gr_area(c1,r1); //调用友元函数,如同调用普通函数
if (x<0)
cout <<"Area of rectangle is larger." <<endl;
else if (x==0)
cout << "Rectangle and Circle have the same area" << endl;
else cout << "Area of circle is larger." <<endl;
} 运行结果为:
Area of circle is larger.
C++程序设计课件 设计制作:徐龙琴 52
2 友元类
⑴ 友元类, 即 一个类可以作为另一个类的友元,这就 意味着
这个类的所有成员函数 都是 另 一个 类的友元函数。
即该类的友元函数都可以访问另一个类中的隐藏
信息(包括私有成员和保护成员)。 友元类 可在
另一个类 的 公有 或 私有 部分 进行说明, 说明方法
如下:
friend 类名 ; //友元类类名
C++程序设计课件 设计制作:徐龙琴 53
class A
{ …
public,
friend class B; //说明 B是 A的友元类
…
};
例,以下说明类 B是类 A的友元类:
使用使用友元类时注意:
①友元关系 不能被继承 。
② 友元关系是单向的,不具有交换性 。
③ 友元关系 不具有传递性 。
C++程序设计课件 设计制作:徐龙琴 54
#include<iostream.h>
#include”math.h”
class A
{ private,int x;
public,A( ){ x=5; }
friend class B;
};
class B
{ public,
void disp1(A tmp)
{tmp.x++;cout<<”disp1:x=”<<tmp.x<<endl;};
void disp2(A tmp)
{tmp.x--;cout<<”disp2:x=”<<tmp.x<<endl;};
};
void main()
{ A obj1;
B obj2;
obj2.disp1(obj1);
obj2.disp2(obj1); }
例, 分析下面这个程序的输出结果
运行结果为:
disp1:x=6
disp2:x=4
C++程序设计课件 设计制作:徐龙琴 55
§ 程序举例
例, 设计一个类,数据成员有:月、日、年。成员函数有:输入
日期、判断闰年、输出日期。
#include <iostream.h>
class Date
{private:
int month;
int day;
int year;
public:
void input()
{ cout<<"please input date"<<endl;
cout<<"month:";cin>>month;
cout<<"day:";cin>>day;
cout<<"yeay:";cin>>year;}
int leapyear()
{ return (year%4==0&&year%100!=0)||(year%400==0);}
void print()
{cout<<month<<"/"<<day<<"/"<<year<<endl;}
};
C++程序设计课件 设计制作:徐龙琴 56
void cal(Date *p)
{ p->print();
if(p->leapyear())
cout<<"is leap yeay"<<endl;
else
cout<<"is not leap year"<<endl;
}
void main()
{
Date d;
d.input();
cal(&d);
}
C++程序设计课件 设计制作:徐龙琴 57
例,设计一个学生绩管理系统,能输入学生学号,姓名和成绩
等数据,能按成绩从高到低进行排序,能将排序的结果输出
分析,设计一个学生类,包含三个私有数据成员,即学号 sno,
姓名 sname,和成绩 score;然后在该类中再设计两个公
有成员函数 setdate( )和 display(),分别完成输入
学生的信息和输出学生信息的功能。
C++程序设计课件 设计制作:徐龙琴 58
#include <iostream.h>
#include <string.h>
struct student
{ private:
int sno;
char sname[20];
float score;
public:
void setdate(int no,char name[],float s)
{sno=no;
strcpy(sname,name);
score=s;}
void display()
{cout<<sno<<"\t"<<sname
<<"\t"<<score<<endl;}
};
C++程序设计课件 设计制作:徐龙琴 59
void main()
{ int n,i;
student *p;
int no;
char name[20];
float score;
cout<<"请输入学生的人数,";
cin>>n;
p=new student[n];
cout<<"学号 姓名 成绩 "<<endl;
for( i=0;i<n;i++)
{ cin>>no>>name>>score;
p[i].setdate(no,name,score);}
cout<<"输出结果,"<<endl;
cout<<"学号 \t"<<"姓名 \t"<<"成绩 "<<endl;
for( i=0;i<n;i++)
p[i].display();
delete p; }
C++程序设计课件 设计制作:徐龙琴 60
#include<iostream.h>
#include"stdio.h"
class COUNT
{ int num;
public,
COUNT( );
~ COUNT( );
void process( );
};
COUNT::COUNT( ) { num=0; }
COUNT::~COUNT( ) { cout<<"字符个数,"<<num<<endl; }
void COUNT::process( )
{ while(getchar()!='\n') num++;
cout<<endl; }
void main( )
{ COUNT c;
c.process( );
}
例, 通过 该 程序分析构造函数和析构函数的用法。
运行结果为:
Good!
字符个数,5