240 likes | 373 Views
成员函数的特性. 内联函数 重载性 设置参数的缺省值. 内联函数. 内联函数:函数的函数体放在类体内 外联函数:说明在类体内,定义在类体外。 外联函数在函数头前加上 inline 就变成内联函数了。. 重载性. 成员函数可以重载。构造函数可以重载,析构函数不能重载。. 构造函数和析构函数的调用时间. 6.5 静态成员. 静态成员的提出是为了解决数据共享的问题。 同全局对象相比使用静态数据成员有两个优势: 1 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性
E N D
成员函数的特性 • 内联函数 • 重载性 • 设置参数的缺省值
内联函数 • 内联函数:函数的函数体放在类体内 • 外联函数:说明在类体内,定义在类体外。 • 外联函数在函数头前加上inline就变成内联函数了。
重载性 • 成员函数可以重载。构造函数可以重载,析构函数不能重载。
6.5 静态成员 静态成员的提出是为了解决数据共享的问题。 同全局对象相比使用静态数据成员有两个优势: 1 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性 2 可以实现信息隐藏。静态成员可以是private成员,而全局对象不能。
Exa6-7 • #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(3,7,10),N(14,9,11);//定义对象M,N • M.GetNumber(); • N.GetNumber(); • M.GetSum(); • N.GetSum(); • }
静态数据成员注意事项 1.在类体中的数据成员声明前面加上关键字static 就使该数据成员成为静态的。 2.静态数据成员初始化的格式: <数据类型><类名>::<静态数据成员名>=<值> 一般地,静态数据成员在该类定义之外被初始化,并且不加static ,以免与一般静态变量混淆。 3.必须对静态成员初始化 4.引用静态数据成员时,采用如下格式: <类名>::<静态成员名>
静态成员函数 • 对静态成员函数的引用不需要用对象名。 • 在静态成员函数的实现中,不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员。如果静态成员函数内要引用非静态成员,可以通过对象来引用。
#include <iostream.h> • class M • {public: • M(int a){A=a; B+= a;} • static void f1(M m); • 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); • M::f1(Q); • }
6.6 友元 类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。 友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
友元通俗的理解就是允许另一个类或函数访问你的类的一种机制。友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类 . 友元函数是一种定义在类外部的普通函数,其说明在类内部,关键字:friend. 友元函数不是成员函数,但是可以访问类中的私有成员。 友元函数的特点是能够访问类中私有成员的非成员函数。从语法上看,和普通函数一样。
例6-10 该程序的Point类中说明了一个友元函数Distance( ),它在说明时前面加一个friend关键字,标识它不是成员函数,而是友元函数。它不需要指出所属的类,但是可以引用类中的私有成员,如a.x,b.x,a.y,b.y,都是类的私有成员。P1.Getxy(),p2.Getxy()是成员函数的调用。在调用友元函数时,如Distance(p1,p2)是友元函数的调用,不需要对象表示。
友元类 友元还可以是类,即一个类可以作为另一个类的友元。当一个类作为另一个类的友元时,该类的所有成员函数都是另一个类的友元函数。
整个类作为另一个类的友元: class x { friend class y; //…… }; 例6-11
6.7 类的作用域 • 类的作用域简称类域,是指在类的定义中由花括号括起来的部分。每个类都有自己的类域,该类的成员局部于类所属的域中。 • 类域中可以定义变量,也可以定义函数,但定义变量不能使用auto,register和extern等修饰符,只能用static,定义的函数不能用extern。 • 文件域可以包含类域。类域介于文件类和函数类之间。
作用域的种类 • 按作用域的大小可分为: • 程序级:作用域最大,包含着该程序的所有文件,程序级的有外部函数和外部变量。 • 文件级:内部函数和外部静态变量,作用域仅在定义它的文件内。 • 函数级:函数的形参和在函数内定义的自动类变量和内部静态类变量以及语句标号,这些标识符的定义域都是在它所定义的函数体内。 • 块级:定义在分程序中、if语句中、switch语句以及循环语句中的自动类和静态类变量。
6.8 局部类和嵌套类 • 在一个函数体内定义的类称为局部类。局部类只能使用外围作用域中的对象和函数进行联系。局部类中不能定义 static 成员函数,并且所有成员函数都必须定义在类体内。局部类很少使用。
例. • int a; • void fun() • { • static int s; • class A//定义局部类A • { • public: • void init(int i){s=i;} • }; • A m; • m.init(10); • }
嵌套类 • 在一个类中定义的类称为嵌套类,定义嵌套类的类称为外围类。 • 定义嵌套类的目的在于隐藏类名,减少全局标识符,从而限制用户使用该类建立对象,提高类的抽象能力,并强调类之间的主从关系。
例 • class A//外围类A • { • public: • class B//嵌套类B • { public: • private: • }; • void f(); • private: • int a; • };
注意事项 • 1、从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用。如果在外围类的作用域内使用该类名时,需要加名字限定。 2、从访问权限的角度来看,嵌套类名与它的外围类的对象成员名具有相同的访问权限规则。不能访问嵌套类的对象中的私有成员函数,也不能对外围类的私有部分中的嵌套类建立对象。 3、嵌套类中的成员函数可以在它的类体外定义。
4、嵌套类中说明的成员不是外围类中对象的成员,反之亦然。嵌套类的成员函数对外围类的成员没有访问权,反之亦然。因此,在分析嵌套类与外围类的成员访问关系时,往往把嵌套类看作非嵌套类来处理。 4、嵌套类中说明的成员不是外围类中对象的成员,反之亦然。嵌套类的成员函数对外围类的成员没有访问权,反之亦然。因此,在分析嵌套类与外围类的成员访问关系时,往往把嵌套类看作非嵌套类来处理。 • 5、在嵌套类中说明的友元对外围类的成员没有访问权。6、如果嵌套类比较复杂,可以只在外围类中对嵌套类进行说明,关于嵌套的详细的内容可在外围类体外的文件域中进行定义。
6.9 对象的生存期 • 对象的生存期指对象从被创建到释放为止的时间。 • 按生存期的不同,对象可分为: • 1. 局部对象:当对象被定义时调用构造函数,该对象被创建,当程序退出定义该对象所在的函数体或程序块时,调用析构函数,释放该对象。 • 2. 静态对象:当程序第一次执行所定义的静态对象时,该对象被创建,当程序结束时释放。 • 3.全局对象:程序开始时,调用构造函数创建,当程序结束时,调用析构函数释放。