第十二章静态友元
第6章-静态成员与友元

6.1.2 静态数据成员
静态数据成员的定义分为两个必不可少的部分:类内声 明、类外初始化。 在类内,声明静态数据成员的格式为 :
static 数据类型 静态数据成员名;
在类外初始化的形式为:
数据类型 类名::静态数据成员名=初始值;
除了在初始化时可以在类外通过类对静态成员赋初 值外,其他情况下对静态成员的存取规则与一般成员相 同。即:在类内可以任意存取;在类外,通过对象只能 访问存取属性为public的成员。
6.1.1 静态成员的需要性
有一些属性是类中所有成员所共有的,属于类的一
部分,但既不适于用普通成员表示,也不适于全局 变量表示的数据,用静态成员表示。
对象个数 对象链表头、尾指针 类的状态
一个类对象的public成员可被本类的其他对象存取,
即可供所有对象使用,但是此类的每个对象都各自 拥有一份,不存在真正意义上的共享成员。所以, C++提供了静态成员,用以解决同一个类的不同对 象之间数据成员和函数的共享问题。
6.1.2 静态数据成员
注意: 对静态数据成员的访问还可以通过类的成员函数来进行。
P335例子
§6-1 静态成员
#include <iostream.h> class Myclass { public: Myclass(int,int,int); void GetNumber(); void GetSum(); private: int A,B,C; static int Sum; }; int Myclass::Sum=0; Myclass(int a,int b,int c) { A=a; B=b; C=c; Sum+=A+B+C; } void GetNumber() {cout<<“Number=”<<A<<“,”<<B <<“,”<<C<<endl;} void GetSum() {cout<<“Sum=”<<Sum<<endl;} void main() { Myclass M(3,7,10),N(14,9,11); M.GetNumber(); N.GetNumber(); M.GetSum(); N.GetSum(); }
实验四 静态成员与友元

实验四静态成员与友元【实验目的】1.掌握友元函数的定义、使用方法以及特点。
2.握静态成员函数和静态数据成员的功能。
【实验内容】1.调试下列程序,写出输出结果,并分析输出结果。
#include "iostream.h"class My{public:My(int aa){A=aa;B-=aa;}static void fun(My m);private:int A;static int B;};void My::fun(My m){cout<<"A="<<m.A<<endl;cout<<"B="<<B<<endl;}int My::B=100;int main(){My P(6),Q(8);My::fun(P);Q.fun(Q);return 0;}分析:2.设计一个含有静态成员、静态成员函数的程序,分析程序结果,理解静态成员(函数)与类和对象的关系。
参考程序:#include<iostream.h>class A{friend class B;//友元类的声明public:void Set(int i){x=i;}friend int add(A & f1);// 友元函数的声明void Display(){cout<<"x="<<x<<",y="<<y<<endl;}private:int x;static int y;};int add(A & f1){return f1.x+1;}class B{public:B(int i,int j);void Display();private:A a;//A类的对象a作为类B的私有成员};int A::y=1;//静态成员必须先赋初值B::B(int i,int j){a.x=i;A::y=j;}void B::Display(){cout<<"x="<<a.x<<",y="<<A::y<<endl; }void main(){A b;b.Set(5);//友元函数的调用cout<<add(b)<<endl;b.Display();B c(6,9);//a.x=6,X::y=9;c.Display();b.Display();}问题:(1)分析友元函数add()的定义、调用与成员函数的区别。
实验6-静态成员和友元

#include <iostream>
#include <cstring>
using namespace std;
class CTeacher;
class CStudent
{
public:
CStudent(char *n, int a);
~CStudent();
int age;
friend class CTeacher;
cout<<"CStudent::nTotalObj="<<CStudent::nTotalObj<<endl;
}
问题一:以上程序编译能通过吗,为什么?
问题二:成员变量nTotalObj在程序中起什么作用,它是如何实现的?
问题三:如果规定该程序的主函数和类CStudent中的成员变量的属性不允许改变,应该如何改正该程序?
private:
char *name;
};
CStudent::CStudent(char *n, int a):age(a)
{
int nLen = strlen(n);
name = new char[nLen+1];
strcpy(name,n);
name[nLen] = '\0';
}
CStudent::~CStudent()
2.理解下面的程序,并在VC++6.0下运行查看结果,回答程序后面的问题。
#include <iostream.h>
#include <string.h>
class CStudent
{
静态成员与友元

静态成员属于类本身,只有一个实例,存储在静态存储区,而友元不属于类本身,可以访问类的私有和 保护成员,但不能访问类的静态成员。
使用场景的比较
静态成员
适用于需要在程序中全局访问或管理的数据或函数,例如计数器、 单例模式等。
友元
适用于需要访问类的私有和保护成员的外部函数或类,例如输入 输出流、字符串处理函数等。
02
在某些算法中,需要使用到类 的私有和保护成员,这时可以 使用友元函数来提供访问权限 。
03
在实现某些设计模式(如策略 模式)时,可能需要使用友元 函数来提供对类的内部状态的 访问。
友元函数与成员函数的区别
访问权限
01
友元函数可以访问类的私有和保护成员,而成员函数只能访问
公有成员。
调用方式
02
友元函数不是通过对象来调用的,而成员函数是通过对象来调
总结
静态成员适用于需要全局访问或管理的数据或函数,而友 元适用于需要访问类的私有和保护成员的外部函数或类。
04
示例代码
静态成员函数示例
总结词
静态成员函数属于类本身,而不是类的对象。它们可以在没有类的对象的情况下调用。
详细描述
静态成员函数可以直接通过类名调用,而不需要类的对象实例。它们通常用于实现与类相关但不依赖于类中特定 对象的功能。例如,一个计算类中静态成员函数可以计算两个数的和或差,而不关心具体是哪两个数。
友元函数可以是一个全局函数、另一个 类的成员函数或一个嵌套函数。
友元函数不是类的成员函数,但它可以 访问类的非静态成员变量,但不能访问 静态成员变量。
特点
友元函数不受类的访问控制限制,可以 直接访问类的私有和保护成员。
友元函数的使用场景
实验4 静态变量、友元

实验四静态变量、友元1、阅读程序要阅读的程序中存在语法错误,请将其找出来,能用自己的话说清理由#include <iostream>#include <string>using namespace std;class Box{public:Box(int h,int w,int l):height(h),width(w),length(l){}int volume( ){return height*width*length;};private:static int height; //静态的数据成员int width;int length;};int main(){Box b(2,3,4);cout<<"volume is "<<b.volume()<<endl;return 0;}答: Box(int h,int w,int l):height(h),width(w),length(l){}出现错误,不能用参数初始化对静态数据成员初始化.2、书后第九题#include<iostream>using namespace std;class sell{public:sell(int qu):quantity(qu){}void input();static void display();static int average();void kix();private:int quantity;int num;float price;static float discount;static float sum;static int n;};float sell::discount=0.98;float sell::sum=1;int sell::n=3;void sell::kix(){if(n>10)sum=quantity*discount*price;elsesum=quantity*price;}int sell::average(){return (sum/n);}void sell::display(){cout<<"总销售价:"<<sum<<endl; }void sell::input(){ cout<<"销货员号:";cin>>num;cout<<"销货件数:";cin>>quantity;cout<<"销货单价";cin>>price;}int main(){ sell a[3]={sell(3),sell(1),sell(0)};for(int i=0;i<3;i++){ cout<<i+1<<endl;a[i].input();a[i].kix();a[i].display();a[i].kix();cout<<"平均售价:"<<a[i].average()<<endl;}return 0;}3、阅读下面的程序,仔细阅读注释。
实验4 静态成员与友元

3.2 实验与实践任务3.2.1 实验名称静态成员和友元3.2.2 实验目的1.掌握静态成员的定义和使用。
2.掌握友元的定义和使用。
3.2.3 实验要求1.调试程序要记录调试过程中出现的问题及解决办法;2.编写程序要规范、正确,上机调试过程和结果要有记录,并注意调试程序集成环境的掌握及应用,不断积累编程及调试经验;3.在编写程序时,要按照多文件结构来组织程序。
4.做完实验后给出本实验的实验报告,实验报告的内容包括实验目的、实验内容和结果分析。
3.2.4 实验内容【P1】商店销售某一商品,商店每天公布统一的折扣(discount)。
同时允许销售人员在销售是灵活掌握售价(price),在此基础上,对一次购10件以上者,还可以享受9.8折优惠。
现在已知当天3名销售员的销售情况为:销售员货号(num)销货件数(quantity)销货单价(price)101 5 23.5102 12 24.56103 100 21.5请编程序,计算出当日此商品的总销售款sum,以及每件商品的平均售价。
要求用静态数据成员和静态成员函数【P2】创建一个SavingsAccount类:用static(静态)数据成员包含每个存款人的annualInterestRate(年利率)。
类的每个成员包含一个private数据成员savingsBalance,表示当前存款额。
提供一个calculateMonthlyInterest 成员函数,计算月利息,用savingsBalance乘以annualInterestRate除以12取得,并将当月月息加入savingsBalance。
提供一个静态成员函数modifyInterestRate,将静态annualInterestRate设置为新值。
实例化两个不同的SavingsAccount对象saver1和saver2,余额分别为$2 000.00和$3 000.00 将annualInterestRate设置为3%,计算每个存款人的月息并打印出新的结果。
C++实验报告四--静态成员与友元

南昌航空大学实验报告2011年11月9号课程名称:面向对象程序设计B 实验名称:静态成员与友元班级:姓名:同组人:无指导教师评定: 签名:一、实验目的(1)学习静态成员的使用,理解静态成员的特殊用途。
(2)学习友元函数及友元类,领会友元类的作用。
二、实验内容应用VC++6.0的编辑环境构造一个类Stack,设计一个整数链表类,实现栈操作。
类中需有记录结点个数的数据成员(静态成员),要有判空操作。
编制应用程序,取100次随机数(<1000),如果取到的随机数比前一个随机数大的话,入栈,然后逐个取出(即出栈过程)求其和。
用堆分配方法逐个产生满足条件(递增有序)的结点,插入栈中,每当出栈时,要及时将结点删除,求和工作放在类定义外(友元)。
注意:栈中最多会有100个元素,最少会有一个元素,这是由条件(递增有序)决定的。
三、概要设计要实现的功能:构造一个类Stack、设计一个整数链表类,实现栈操作、取100次随机数(<1000),如果取到的随机数比前一个随机数大的话,入栈,然后逐个取出(即出栈过程)求其和。
函数原型为:struct SNode{int data;SNode *next;};class Stack{public:Stack();~Stack();void Push(int e);//insert a data into stackint Pop();//delete a data from stackfriend int GetSum(Stack &);//get sum of stack,friend function//friend class getsum;// get sum of stack,friend class,you can try it using friend classstatic int num;//static numberprivate:SNode *head;};四、详细设计定义类Stack的函数:Stack::Stack(){Head=new SNode;Head->next=NULL;}设计一整数链表类,实现取100次随机数(<1000),如果取到的随机数比前一个随机数大的话,入栈,然后逐个取出的栈操作的函数:void Stack::Push(int e){SNode *p,*q;if(!(p=new SNode))exit(0);p->data=e;q=Head;while(q->next)q=q->next;q->next=p;p->next=NULL;num++;}int Stack::Empty(){return !num;}int Stack::Pop(){int e;if(Empty()){cout<<"The Stack is empty!"<<endl; exit(0);}SNode *p,*q;p=Head;q=p;while(p->next){q=p->next;if(!q->next)break;p=p->next;}p->next=NULL;e=q->data;delete q;num--;return e;}int Stack::GetTop(){int e;if(Empty()){cout<<"The Stack is empty!"<<endl; exit(0);}SNode *p;p=Head;while(p->next){p=p->next;}e=p->data;return e;}求和的函数为:int GetSum(Stack &a){int sum=0,m,tmp;m=a.num;cout<<endl<<"Pop Stack List is:"<<endl;for(int i=0;i<m;i++){tmp=a.Pop();cout<<" "<<tmp;sum+=tmp;}cout<<endl;return sum;}五、程序调试在函数调试的过程中,出现了以下错误提示信息:1、“Stack::Empty”: 函数调用缺少参数列表;请使用“&Stack::Empty”创建指向成员的指针原因为将语句if(Empty())中的括号()漏掉了。
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
此课件下载可自行编辑修改,供参考! 感谢您的支持,我们努力做得更好!
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
§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. 静态成员函数的说明和定义与静态数据成员一样,函数实 现可在类体内,也可在类体外,与一般成员函数相同。 在静态成员函数的实现中,可以直接使用静态成员,可以 通过对象来使用非静态成员。
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;
a.showcount(); b.showcount(); count(10); a.showcount(); b.showcount(); }
结果: 0 0 10 10
从例子中可见,定义静态数据成员时,可根据需要说明其 访问权限控制符。 静态数据成员的生命期是全局的,编译器只对它进行一次 初始化,将始终保持其值,直到下次改变为止。
在一个类中,若将一个数据说明为static,则该数据称为静 态数据,它告诉编译器无论建立多少个该类的对象,都只有一 个静态数据的拷贝,这个拷贝被所有类对象共享。 静态数据属于类而共享,不属于对象独有。它的值对每个 对象都是一样的。
对静态数据成员的值的更新,即是对所有对象的该静态数 据成员值的更新。
友元函数具有下述特点: 1、在类体内说明,在函数的类型说明符前加关键字friend;
2、在类体外定义,定义格式与普通函数相同;
3、友元函数是非成员函数,在调用上与普通函数相同; 4、友元函数可以直接访问该类中的私有成员。 例如:下面程序段说明友元函数的说明和定义方法 class X { int i; friend void func(X *, int); //friend function declaration public void member_func(int); };
下图形象地说明了一个类Group 的四个对象的存储分配情 况,每个对象具有自己的字符变量ch 的拷贝内存空间,而共享 静态型变量s,即静态变量s 在存储上只需拷贝一处就可以供所 有对象使用。 Group c class Group { char ch;
char ch; static int s;
}
例: Class Student { public: Student( ) {computerscore=0;} Student(float score) { computerscore=score; totalscore+=score; count++; } static float totalsum( ) { return totalscore; }
void func(X *ptr, int a) { ptr->i=a; } void X::member_func(int a) { i=a; }
static float average( ) { return totalscore/count; } private: float computerscore; static float totalscore; static float averagescore; static int count; } float Student::totalscore=0; float Student::averagescor=0; float Student::count=0;
第十二章
目
录
§12.1
§12.2 §12.3
静态数据
静态成员函数 友元
第十二章小结
第十二章 静态成员与友元
全局对象是实现数据共享的一种方法,由于它处处可见, 因此不够安全,应尽量在程序中少用全局对象。
实现类的多个对象之间的数据共享,可使用静态成员。
静态成员包括静态数据成员和静态成员函数。 友元函数也是一种普通的C++ 函数,但是它可以访问类 的保护或私有成员,方便编程,提高了效率,同时也破坏了 类的封装性。 本章内容:介绍如何使用静态数据成员和静态成员函数, 了解友元的使用方法及作用的局限性。
§12.3 友元(Friends)
类具有封装性,类中的私有数据只有通过该类的成员函数 才可以访问。如果在程序中需要访问类的私有成员,就必须通 过对象来调用类的成员函数,频繁调用成员函数将影响程序运 行效率。
为解决上述问题,C++ 提供一种友元机制,友元可以不通 过调用成员函数就可以直接访问类的私有数据,以提高程序运 行效率。 友元机制在数据封装这堵不透明的墙上开了一个小孔,友 元的使用要慎重。
结果: A=6,B=24 A=8,B=24
//类名调用 //对象调用
例如:下面是另一个程序例子
#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; };
静态数据使用关键字static,静态数据成员在类体中说明, 在类体外定义,以分配存储空间并初始化。
例如:下面例子说明了静态数据的说明和初始化方法。 #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;
§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.
void main( ) {Student sd1(92),sd2(85),sd3(80); cout<<sd1.totalsum( )<<endl; cout<<sd2.average( )<<endl; cout<<sd3.average( )<<endl; }
运行结果:
257 85.66 85.66
对静态成员函数的访问,在程序中可使用如下方式:
<类名>::<静态成员函数名>(<参数表>)
或 <对象名>.<静态成员函数名>(<参数表>) 静态成员函数只属于一个类,而不属于类中的任何对象。
例如:下面是定义和使用静态成员函数的例子 #include <iostream.h> class M { public: M(int a) { A=a; B+=a; } static void fun(M m); //说明静态成员函数 private: int A; static int B; }
Group a char ch;
Group b
static int s;
char ch;
Group d char ch;
静态数据成员可应用在以下几个方面: (1) 用来保存流动变化的对象个数(如学生人数); (2) 作为一个标志,指示一个特定的动作是否发生; (3) 指向一个链表的第一成员或最后一个成员的指针。
例如:下面程序说明了静态数据成员的定义、初始化和使用的 方法。
#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);
注意:静态成员函数与非静态成员函数的根本区别在于静 态成员函数没有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); }