1 / 28

第十二章 目 录

第十二章 目 录. § 12.1 静态数据. § 12.2 静态成员函数. § 12.3 友元. 第十二章小结. 第十二章 静态成员与友元. 全局对象是实现数据共享的一种方法,由于它处处可见,因此不够安全,应尽量在程序中少用全局对象。 实现类的多个对象之间的数据共享,可使用静态成员。 静态成员包括静态数据成员和静态成员函数。 友元函数也是一种普通的 C++ 函数,但是它可以访问类的保护或私有成员,方便编程,提高了效率,同时也破坏了类的封装性。

baird
Download Presentation

第十二章 目 录

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第十二章 目 录 §12.1 静态数据 §12.2 静态成员函数 §12.3 友元 第十二章小结

  2. 第十二章 静态成员与友元 全局对象是实现数据共享的一种方法,由于它处处可见,因此不够安全,应尽量在程序中少用全局对象。 实现类的多个对象之间的数据共享,可使用静态成员。 静态成员包括静态数据成员和静态成员函数。 友元函数也是一种普通的C++ 函数,但是它可以访问类的保护或私有成员,方便编程,提高了效率,同时也破坏了类的封装性。 本章内容:介绍如何使用静态数据成员和静态成员函数,了解友元的使用方法及作用的局限性。

  3. §12.1 静态数据 A variable that is part of a class, yet is not part of an object of that class, is called a static member. There is exactly one copy of a static member instead of one copy per object, as for ordinary non-static members.

  4. 在一个类中,若将一个数据说明为static,则该数据称为静态数据,它告诉编译器无论建立多少个该类的对象,都只有一个静态数据的拷贝,这个拷贝被所有类对象共享。在一个类中,若将一个数据说明为static,则该数据称为静态数据,它告诉编译器无论建立多少个该类的对象,都只有一个静态数据的拷贝,这个拷贝被所有类对象共享。 静态数据属于类而共享,不属于对象独有。它的值对每个对象都是一样的。 对静态数据成员的值的更新,即是对所有对象的该静态数据成员值的更新。 静态数据使用关键字static,静态数据成员在类体中说明,在类体外定义,以分配存储空间并初始化。

  5. 例如:下面例子说明了静态数据的说明和初始化方法。例如:下面例子说明了静态数据的说明和初始化方法。 #include <iostream.h> #include <stdio.h> class counter { static int count; //在类体内说明静态数据 public: void setcount(int i) { count=i; } void showcount() { cout<<count; } } int counter::count=0; //在类体外定义静态数据 void main() { counter a,b;

  6. a.showcount(); b.showcount(); a.setcount(10); a.showcount(); b.showcount(); } 结果: 0 0 10 10 从例子中可见,定义静态数据成员时,可根据需要说明其访问权限控制符。 静态数据成员的生命期是全局的,编译器只对它进行一次初始化,将始终保持其值,直到下次改变为止。

  7. 例如:下面程序说明了静态数据成员的定义、初始化和使用的方法。例如:下面程序说明了静态数据成员的定义、初始化和使用的方法。 #include <iostream.h> class Myclass { public: Myclass(int a,int b,int c); void getnumber( ); int getsum(Myclass m); private: int A,B,C; static int sum; }; int Myclass::sum(0);

  8. Myclass::Myclass(int a,int b,int c) { A=a; B=b; C=c; sum+=A+B+C; } void Myclass::getnumber(); { cout<<A<<“;”<<B<<“;”<<C<<endl; } int Myclass::getsum(Myclass m) { return Myclass::sum; }

  9. void main() { Myclass M(3,4,5),N(5,6,7); N.getnumber(); cout<<M.getsum(M)<<“;”<<M.getsum(N)<<endl; } 结果: 5; 6; 7 30; 30 注意:在成员函数getsum()中,通过类来使用静态数据成员sum,如:return Myclass::sum; 也可以通过对象来使用sum,如:return m.sum;

  10. Group c char ch; Group a char ch; Group b char ch; Group d char ch; static int s; 下图形象地说明了一个类Group 的四个对象的存储分配情况,每个对象具有自己的字符变量ch 的拷贝内存空间,而共享静态型变量s,即静态变量s 在存储上只需拷贝一处就可以供所有对象使用。 class Group { char ch; static int s; }

  11. 静态数据成员可应用在以下几个方面: • 用来保存流动变化的对象个数(如学生人数); • (2) 作为一个标志,指示一个特定的动作是否发生; • (3) 指向一个链表的第一成员或最后一个成员的指针。

  12. §12.1 静态成员函数(Static member function) A function that needs access to members of a class, yet does not need to be invoked for a particular object, is called a static member function. 静态成员函数的说明和定义与静态数据成员一样,函数实现可在类体内,也可在类体外,与一般成员函数相同。 在静态成员函数的实现中,可以直接使用静态成员,可以通过对象来使用非静态成员。

  13. 对静态成员函数的访问,在程序中可使用如下方式:对静态成员函数的访问,在程序中可使用如下方式: <类名>::<静态成员函数名>(<参数表>) 或 <对象名>.<静态成员函数名>(<参数表>) 静态成员函数只属于一个类,而不属于类中的任何对象。

  14. 例如:下面是定义和使用静态成员函数的例子 #include <iostream.h> class M { public: M(int a) { A=a; B+=a; } static void fun(M m); //说明静态成员函数 private: int A; static int B; }

  15. void M::fun(M m) //定义静态成员函数 { cout<<“A=”<<m.A<<“,”; //通过对象访问非静态变量 cout<<“B=”<<B<<endl; //直接访问静态变量 } int M::B=10; //定义并初始化静态变量 void main() { M P(6),q(8); M::fun(P); //类名调用 q.fun(q); //对象调用 } 结果: A=6,B=24 A=8,B=24

  16. 例如:下面是另一个程序例子 #include <iostream.h> enum access_t {shared, in_used, locked, unlocked}; class access { public: static void set_access(access_t a) { acs=a; } static access_t get_access() { return(acs); } private: static access_t acs; };

  17. access_t access::acs=0; void main() { access obj1,obj2; obj1.set_access(unlocked); if(obj2.get_access()==unlocked) { obj2.set_access(in_used); cout<<“access resource\n”; } else cout<<“locked out\n”; } 输出为:access resource

  18. 注意:静态成员函数与非静态成员函数的根本区别在于静态成员函数没有this 指针,而非静态成员函数有一个隐含的指向当前对象的this 指针。 例如:该例说明一个静态成员函数与任何当前对象都无联系的原因 class Sc { public: void nsfn(int a); //类似于Sc::nsfn(Sc *this, int a); static void sfn(int a); //无this 指针 //…… } void fc(Sc& s) { s.nsfn(10); //转换为Sc::nsfn(&s,10); s.sfn(10); //转变为Sc::sfn(10); }

  19. §12.3 友元(Friends) 类具有封装性,类中的私有数据只有通过该类的成员函数才可以访问。如果在程序中需要访问类的私有成员,就必须通过对象来调用类的成员函数,频繁调用成员函数将影响程序运行效率。 为解决上述问题,C++ 提供一种友元机制,友元可以不通过调用成员函数就可以直接访问类的私有数据,以提高程序运行效率。 友元机制在数据封装这堵不透明的墙上开了一个小孔,友元的使用要慎重。 友元可以是一个函数,称为友元函数;友元可以是一个类,称为友元类。

  20. 一、友元函数 An ordinary member function declaration specifies three logically distinct things: 1、The function can access the private part of the class declaration and 2、the function is in the scope of the class and 3、the function must be invoked on an object (has a this pointer). By declaring a member function static we can give it the first two properties only. By declaring a function a friend, we can give it the first property only.

  21. 友元函数具有下述特点: 1、在类体内说明,在函数的类型说明符前加关键字friend; 2、在类体外定义,定义格式与普通函数相同; 3、友元函数是非成员函数,在调用上与普通函数相同; 4、友元函数可以直接访问该类中的私有成员。 例如:下面程序段说明友元函数的说明和定义方法 class X { int i; friend void func(X *, int); //friend function declaration public void member_func(int); };

  22. void func(X *ptr, int a) //friend function definition { ptr->i=a; } void X::member_func(int a) //member function definition { i=a; } 例如:下面程序说明了友元函数的说明、定义和调用方法。程序功能是求两点间的距离 #include <iostream.h> #include <math.h> class Point { public:

  23. Point(double i, double j) { x=i; y=j; } void Getxy() { cout<<“(”<<x<<“,”<<y<<“)”<<endl; } friend double Distance(Point a, Point b); //友元函数的说明 private: double x,y; }; Double Distance(Point a, Point b) //友元函数的定义 { double dx=a.x-b.x; double dy=a.y-b.y; return sqrt(dx*dx+dy*dy); }

  24. void main() { double d11=3.0,d12=4.0,d21=6.0,d22=8.0; Point P1(d11,d12),P2(d21,d22); P1.getxy(); P2.getxy(); double d=Distance(P1,P2); //友元函数调用 cout<<“Distance is ”<<d<<endl; } 结果: (3,4) (6,8) Distance is 5

  25. 二、友元类 当说明一个类为另一个类的友元时,友元类中的所有成员函数都是另一个类的友元函数。 例如:下面程序说明友元类的应用,并分析程序输出结果 #include <iostream.h> class X { public: friend class Y; //类Y 是类X 的友元类 void set(int i) { x=i; } void display() { cout<<“x=”<<x<<“,”<<“y=”<<y<<endl; }

  26. private: int x; static int y; //静态数据说明 }; class Y { public: Y(int i,int j); void display(); private: X a; //数据成员为类X的对象 }; int X::y=10; //静态数据定义并初始化 Y::Y(int i,int j) { a.x=i; X::y=j; }

  27. void Y::display() { cout<<“x=”<<a.x<<“,”<<“y=”<<X::y<<endl; } void main() { X b; b.set(5); b.display(); Y c(6,9); c.display(); b.display(); } 结果:x=5, y=10 x=6, y=9 x=5, y=9

  28. 第十二章 小结 使用静态数据成员比使用全局变量更优越,全局变量给面向对象程序设计带来的问题就是违背了数据封装的原则。 要使用静态数据成员必须在main()程序运行之前分配空间和初始化。 静态成员不与类的任何特定对象相关联。 友元的作用主要是为了提高程序的运行效率和方便编程。但随着硬件性能的提高,友元的作用也不明显,相反,友元破坏了类的封装性,所以在使用时,应权衡利弊。

More Related