C++第6章 静态成员与友元

合集下载

C#中静态方法与非静态方法(static),公有与私有(public,private)

C#中静态方法与非静态方法(static),公有与私有(public,private)

C#中静态⽅法与⾮静态⽅法(static),公有与私有(public,private)梳理公有与私有,静态与⾮静态的应⽤1)公有与私有public(公有的):声明的⽅法和属性,可以被外部调⽤.private(私有的):声明的⽅法和属性,只能在本类中被调⽤,外部看不到.2)静态与⾮静态static(静态的):声明的⽅法和属性,不需要实例化就能被调⽤(公有/私有).C#静态⽅法与⾮静态⽅法⽐较⼀、C#静态成员:1、静态成员属于类所有,⾮静态成员属于类的实例所有。

2、每创建⼀个类的实例,都会在内存中为⾮静态成员新分配⼀块存储;⼆、C#静态⽅法1、C#静态⽅法属于类所有,类实例化前即可使⽤。

2、⾮静态⽅法可以访问类中的任何成员,静态⽅法只能访问类中的静态成员。

3、因为静态⽅法在类实例化前就可以使⽤,⽽类中的⾮静态变量必须在实例化之后才能分配内存,C#静态⽅法调⽤时⽆法判断⾮静态变量使⽤的内存地址。

所以⽆法使⽤。

⽽静态变量的地址对类来说是固定的,故可以使⽤。

三、C#静态⽅法是⼀种特殊的成员⽅法它不属于类的某⼀个具体的实例,⽽是属于类本⾝。

所以对静态⽅法不需要⾸先创建⼀个类的实例,⽽是采⽤类名.静态⽅法的格式。

1.static⽅法是类中的⼀个成员⽅法,属于整个类,即不⽤创建任何对象也可以直接调⽤!static内部只能出现static变量和其他static⽅法!⽽且static⽅法中还不能使⽤this…等关键字…因为它是属于整个类!2.静态⽅法效率上要⽐实例化⾼,静态⽅法的缺点是不⾃动进⾏销毁,⽽实例化的则可以做销毁。

3.静态⽅法和静态变量创建后始终使⽤同⼀块内存,⽽使⽤实例的⽅式会创建多个内存.4.C#中的⽅法有两种:实例⽅法,静态⽅法.静态⽅法销毁:主进程销毁时,内存中分配的静态⽅法销毁.四、获取类的名称C#静态⽅法中获取类的名称静态⽅法中⽤:string className = System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.FullName;⾮静态⽅法中还可以⽤:string className = this.GetType().FullName;。

C++类静态成员与类静态成员函数详解

C++类静态成员与类静态成员函数详解

C++类静态成员与类静态成员函数详解当将类的某个数据成员声明为static时,该静态数据成员只能被定义⼀次,⽽且要被同类的所有对象共享。

各个对象都拥有类中每⼀个普通数据成员的副本,但静态数据成员只有⼀个实例存在,与定义了多少类对象⽆关。

静态⽅法就是与该类相关的,是类的⼀种⾏为,⽽不是与该类的实例对象相关。

静态数据成员的⽤途之⼀是统计有多少个对象实际存在。

静态数据成员不能在类中初始化,实际上类定义只是在描述对象的蓝图,在其中指定初值是不允许的。

也不能在类的构造函数中初始化该成员,因为静态数据成员为类的各个对象共享,否则每次创建⼀个类的对象则静态数据成员都要被重新初始化。

静态成员不可在类体内进⾏赋值,因为它是被所有该类的对象所共享的。

你在⼀个对象⾥给它赋值,其他对象⾥的该成员也会发⽣变化。

为了避免混乱,所以不可在类体内进⾏赋值。

数据类型类名::静态数据成员名=初值不能⽤参数初始化表对静态成员初始化。

⼀般系统缺省初始为0。

静态成员是类所有的对象的共享的成员,⽽不是某个对象的成员。

它在对象中不占⽤存储空间,这个属性为整个类所共有,不属于任何⼀个具体对象。

所以静态成员不能在类的内部初始化,⽐如声明⼀个学⽣类,其中⼀个成员为学⽣总数,则这个变量就应当声明为静态变量,应该根据实际需求来设置成员变量。

复制代码代码如下:#include "iostream"using namespace std;class test{private:int x;int y;public:static int num;static int Getnum(){x+=5; // 这⾏代码是错误的,静态成员函数不能调⽤⾮静态数据成员,要通过类的对象来调⽤。

num+=15;return num;}};int test::num = 10;int main(void){test a;cout<<test::num<<endl; //10test::num = 20;cout<<test::num<<endl; //20cout<<test::Getnum()<<endl; //35cout<<a.Getnum()<<endl; //50system("pause");return 0;}通过上例可知: x+=5; // 这⾏代码是错误的静态函数成员必须通过对象名来访问⾮静态数据成员。

C++类中的静态成员变量和静态成员函数的作用

C++类中的静态成员变量和静态成员函数的作用

数据成员可以分静态变量、非静态变量两种.静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员不能访问非静态的成员..因为静态成员存在于内存,所以非静态成员可以直接访问类中静态的成员.非成静态员:所有没有加Static的成员都是非静态成员,当类被实例化之后,可以通过实例化的类名进行访问..非静态成员的生存期决定于该类的生存期..而静态成员则不存在生存期的概念,因为静态成员始终驻留在内容中..一个类中也可以包含静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数..分两个方面来总结,第一方面主要是相对于面向过程而言,即在这方面不涉及到类,第二方面相对于面向对象而言,主要说明static在类中的作用。

一、在面向过程设计中的static关键字1、静态全局变量定义:在全局变量前,加上关键字static 该变量就被定义成为了一个静态全局变量。

特点:A、该变量在全局数据区分配内存。

B、初始化:如果不显式初始化,那么将被隐式初始化为0(自动变量是随机的,除非显式地初始化)。

C、访变量只在本源文件可见,严格的讲应该为定义之处开始到本文件结束。

例〔摘于C++程序设计教程---钱能主编P103〕://file1.cpp//Example 1#include <iostream.h>void fn();static int n; //定义静态全局变量void main(){n=20;cout < <n < <endl;fn();}void fn(){n++;cout < <n < <endl;}D、文件作用域下声明的const的常量默认为static存储类型。

静态变量都在全局数据区分配内存,包括后面将要提到的静态局部变量。

对于一个完整的程序,在内存中的分布情况如以下图:代码区全局数据区堆区栈区一般程序的由new产生的动态数据存放在堆区,函数内部的自动变量存放在栈区。

面向对象的程序设计语言――C++(第二版)-习题参考答案

面向对象的程序设计语言――C++(第二版)-习题参考答案

面向对象的程序设计语言――C++(第二版)-习题参考答案课后习题答案以及代码习题参考答案第1章1.填空题C++语言概述(1)函数说明,函数体(2)声明区,主程序区,函数定义区(3)多态性(4)namespace,using(5)std(6)cin,(7)//(8)对数据的操作2.判断题(1)对(2)错(3)错(4)错(5)错3.改错题(1)没有函数体,应改为void main() {};(2)语句没有分号,应改为using namespace myspace;(3)cout和操作符共同完成输出的功能,应改为cout“ Input your name:";(4)应改为#include iostream.h4.简答题5.编程题(略)(略)第2章1.选择题基本数据类型、运算符与表达式(1)B (2)D (3)B (4)D (5)B课后习题答案以及代码2.简答题(1)(a)、(c)(e)、(f)、(g)、(h)、(i)(2)(a)、(g)、(i)、(j)(3)(a)5.5(b)0(c)20(d)0,0(e)1(f)1,2(g)3(h)-40(i)2(j)3(k)s1='0's1='9'(l)N!=03.读程序写结果(1)0,15(2)(1、1、1),(-1、-1、-1)(3)(a)a*a+2*a*b+b*b(b)4.0/3.0*3.__-__R*R*R(c)5.0/9.0*(F-32)(d)b=ab=c(4)364143(5)x=14.编程题(略)第3章1.选择题(1)B (2)A (3)A (4)C2.判断题(1)错(2)对(3)对(4)错3.读程序写结果(1)C++的控制语句5)A 5)错((课后习题答案以及代码12 23 3 34 4 4 45 5 5 5 5(2)11 2 11 2 3 2 11 2 3 4 3 2 11 2 3 4 5 4 3 2 1(3)j的值为0;i的值为2;4.编程题(略)第4章1.填空题函数(1)void(2)静态全局变量,static(3)函数重载(4)inline(5)递归函数(6)宏定义命令,文件包含命令,条件编译命令2.判断题(1)错(2)错(3)错(4)错(5)错(6)对(7)错(8)错(9)对(10)对3.读程序写结果(1)x=7,y=4x=9,y=5(2)34.56101(3)162228(4)12 15 18 21 24课后习题答案以及代码(5)2,1,4,1,3,2,1,4.简答题5.编程题(略)(略)第5章1.选择题构造数据类型(1)C (2)D (3)A (4)B (5)C 2.判断题(1)错(2)对(3)对(4)错(5)错3.读程序写结果(1)153(2)422 5 6 8 10(3)__,21(4)419(5)6904(6)43214.编程题(略)第6章1.填空题(1)类,对象,类(2)数据成员,成员函数(3)不能(4)private,protected,public,private (5)成员函数类和对象课后习题答案以及代码(6)friend(7)类名,作用域运算符(8)对象名.成员名,指针变量名-成员名,(*指针变量名).成员名(9)构造,析构,构造,析构(10)常量数据,引用数据(11)全局,数据类型,所属的类(12)常成员,只读(13)成员,友元(14)类数据成员,类成员函数(15)this(16)浅拷贝2.选择题(1)C (2)C (3)B (4)C (5)B(6)C (7)D (8)B (9)C (10)D(11)A (12)C (13)D (14)D (15)B3.改错题(1)man1.salary=1000.00; 不能在类外访问类的私有成员(2)float r=0;和float c=0; 类本身是抽象的,不能在类的定义体中给其数据成员赋值}后缺少分号“;”(3)成员函数void setdata(float x1,float y1,float r);没有实现(4)构造函数名point()应与类名同名,为Point没有头文件包含#include iostream.h4.读程序写结果题(1)x=0,y=0x=100,y=200(2)x=100,y=200x=1000,y=2022年t=3.14(3)Sta::fun2()=10s.fun2()=11r.a=20(4)Constructor1 called!x=0Constructor2 called!x=100Destructor called!Destructor called!(5)课后习题答案以及代码575.简答题6.编程题(略)(略)第7章1.填空题(1)继承(2)基类,派生类(3)private,protected,public,private (4)不可访问,保护,公有(5)私有(6)单(一),多(重)(7)赋值兼容规则(8)静态,动态(9)抽象类2.选择题继承和派生(1)B (2)A (3)B (4)C (5)B (6)A (7)D (8)B (9)B (10)B(11)D (12)B3.改错题(1)本题的错误主要是数据成员的访问权限问题:基类的私有成员在派生类中不可访问,如fb()函数中的a3=30;语句;类的私有和保护成员在类外不能访问,如main函数中的x.a2 =20;.a3=30; ,y.a2=200; ,y.a3=300; ,y.b2=2022年;和y.b3=3000;语句。

黄日华

黄日华

实验四
友元和静态成员
一、实验目的
2.学习类的静态成员的使用。

3.学习多文件结构在C++程序中的使用。

二、实验任务
1.实现客户机(CLIENT)类。

定义字符型静态数据成员ServerName。

保存其服务器名称;整型静态数据成员ClientNum,记录已定义的客户数量;定义静态函数ChangeServerName()改变服务器名称。

在头文件client.h中定义类,在文件client.cpp中实现.在文件test.cpp中测试这个类,观察相应的成员变量取值的变化情况。

(提示:新建一个空的控制台项目test,添加头文件client.h,在其中定义类CLIENT,注意使用编译预处理命令;再添加源程序文件client.cpp,在其中实现CLIENT类,注意静态成员变量的使用方法;再添加文件test.cpp,在其中定义main()函数,测试CLIENT类,观察相应的成变量取值的变化情况,注意把相关文件include进来)
2. 编写一个球队程序,其中有两个类:一个是女队类girls_ball,另一个是男队类boys_ball。

每一个类分别有自己的友元函数来计算男、女队员的平均击球率。

两个类还共用两个友元函数:一个是友元函数gbAvg(),用来计算和打印男、女队员总的平均击球率;另一个是友元函数print(),用来打印男、女队员的个人信息。

编一个主程序测试他们
三、实验步骤。

C++友元函数和友元类(C++friend)详解

C++友元函数和友元类(C++friend)详解

C++友元函数和友元类(C++friend)详解私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接⼝(成员函数)间接地进⾏。

这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的⿇烦。

是从结构化的C语⾔发展⽽来的,需要照顾结构化设计程序员的习惯,所以在对私有成员可访问范围的问题上不可限制太死。

C++ 设计者认为,如果有的程序员真的⾮常怕⿇烦,就是想在类的成员函数外部直接访问对象的私有成员,那还是做⼀点妥协以满⾜他们的愿望为好,这也算是眼前利益和长远利益的折中。

因此,C++ 就有了友元(friend)的概念。

打个⽐⽅,这相当于是说:朋友是值得信任的,所以可以对他们公开⼀些⾃⼰的隐私。

友元分为两种:友元函数和友元类。

友元函数在定义⼀个类的时候,可以把⼀些函数(包括全局函数和其他类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了。

将全局函数声明为友元的写法如下:friend 返回值类型函数名(参数表);将其他类的成员函数声明为友元的写法如下:friend 返回值类型其他类的类名::成员函数名(参数表);但是,不能把其他类的私有成员函数声明为友元。

关于友元,看下⾯的程序⽰例。

1. #include<iostream>2. ug namespace std;3. class CCar; //提前声明CCar类,以便后⾯的CDriver类使⽤4. class CDriver5. {6. public:7. void ModifyCar(CCar* pCar); //改装汽车8. };9. class CCar10. {11. private:12. int price;13. friend int MostExpensiveCar(CCar cars[], int total); //声明友元14. friend void CDriver::ModifyCar(CCar* pCar); //声明友元15. };16. void CDriver::ModifyCar(CCar* pCar)17. {18. pCar->price += 1000; //汽车改装后价值增加19. }20. int MostExpensiveCar(CCar cars[], int total) //求最贵⽓车的价格21. {22. int tmpMax = -1;23. for (int i = 0; i<total; ++i)24. if (cars[i].price > tmpMax)25. tmpMax = cars[i].price;26. return tmpMax;27. }28. int main()29. {30. return 0;31. }这个程序只是为了展⽰友元的⽤法,所以 main 函数什么也不做。

c语言程序设计教程慕课版第2版答案

c语言程序设计教程慕课版第2版答案

c语言程序设计教程慕课版第2版答案一、简介本文档是对慕课版《c语言程序设计教程》第2版的习题答案进行总结和整理。

通过这份答案文档,读者可以更好地理解和掌握C语言程序设计的相关知识。

二、习题答案1. 基本概念与语法1.1 什么是C语言?C语言是一种计算机编程语言,最初由丹尼斯·里奇在20世纪70年代开发出来。

它是一种通用、高级的编程语言,适用于各种计算机平台和操作系统。

1.2 C语言的基本语法有哪些?C语言的基本语法包括注释、数据类型、变量、运算符、控制流语句等。

下面是一些常用的C语言基本语法:•注释:用于说明程序的文字,不会被编译器执行,可以提高代码的可读性。

•数据类型:C语言提供了多种数据类型,包括整型、浮点型、字符型等。

•变量:用于存储数据的容器,必须先声明后使用,并指定数据类型。

•运算符:用于执行各种算术、逻辑和关系操作。

•控制流语句:用于控制程序的执行流程,包括条件语句、循环语句等。

2. 数组与字符串2.1 什么是数组?数组是一组相同类型的数据元素的集合,通过下标访问数组元素。

数组有固定的大小,在声明时指定数组的长度。

2.2 如何声明和初始化数组?声明数组的一般语法如下:数据类型数组名称[数组长度];例如,声明一个包含5个整数的数组:int numbers[5];可以通过下标来访问数组元素,下标从0开始,例如,访问第一个元素:int x = numbers[0];可以使用初始化列表的方式初始化数组,例如:int numbers[5] = {1, 2, 3, 4, 5};2.3 什么是字符串?字符串是一串字符的序列,以空字符(’\0’)结尾。

在C语言中,字符串可以用字符数组来表示。

2.4 如何声明和初始化字符串?声明字符串的一般语法如下:数据类型字符数组名称[长度];例如,声明一个长度为10的字符数组:char str[10];可以使用字符串字面值(用双引号括起来的一串字符)来初始化字符数组,例如:```c char str[10] =。

C#中的静态成员、静态方法、静态类介绍

C#中的静态成员、静态方法、静态类介绍

C#中的静态成员、静态⽅法、静态类介绍1.静态成员、实例成员1.1定义及说明数据成员:静态成员:静态成员变量是和类相关联的,可以作为类中"共"有的变量(是⼀个共性的表现),他不依赖特定对象的存在,访问的时候通过类名加点操作符加变量名来访问.实例成员:实例成员变量是和对象相关联的,访问实例成员变量依赖于实例的存在.函数成员:静态⽅法:静态⽅法是不属于特定对象的⽅法,静态⽅法可以访问静态成员变量和静态⽅法;静态⽅法不可以直接访问实例变量和实例⽅法,可以间接调⽤,⾸先要创建⼀个类的实例,然后通过这⼀特定对象来调⽤静态⽅法;实例⽅法:⼀个实例⽅法的执⾏与特定对象关联,他的执⾏需要⼀个对象存在。

实例⽅法可以直接访问静态变量和实例变量,当多个实例对象存在时,内存中并不是存在美个特定的实例⽅法的拷贝,⽽是,相同类的所有对象都共享每个实例⽅法的⼀个拷贝(实例⽅法只占⽤“⼀套”空间)。

静态⽅法和实例⽅法的访问权限表静态成员变量静态⽅法实例成员变量实例⽅法静态⽅法直接访问直接访问不可直接访问不可直接访问实例⽅法直接访问直接访问直接访问直接访问总之:实例⽅法的存在必须要有对象实例的存在,如果对象实例不存在,则实例⽅法也就没有调⽤它的主⼈。

静态⽅法的存在前提是类的存在,所以⽆需声明和New对象。

1.2代码演⽰class Program{static void Main(string[] args){Class1.CallObjectFunc();//静态调⽤Console.WriteLine(Environment.NewLine);Class1 tmpClass = new Class1();//实例调⽤tmpClass.ObjectFunc();Console.ReadKey();}}class Class1{static int Class_m = 9;//静态成员private int object_m = 8;//实例成员public static void CallObjectFunc(){Console.WriteLine("------------静态⽅法调⽤开始:");Class1 class1 = new Class1();class1.ObjectFunc();Console.WriteLine("object_m:" + class1.object_m.ToString());Console.WriteLine("------------静态⽅法调⽤结束:");}public void ObjectFunc(){Console.WriteLine("实例⽅法调⽤开始:");Console.WriteLine("Class_m:" + Class_m.ToString());Console.WriteLine("实例⽅法调⽤结束:");}}输出结果:2.静态类类可以声明为 static 的,以指⽰它仅包含静态成员。

C语言程序设计课件第6章 类与对象

C语言程序设计课件第6章 类与对象
(4)构造函数可以重载,即一个类中可以定 义多个参数个数或参数类型不同的构造函数。
2021/7/13
18
【例6.5】 使用构造函数替代例6.3中SetTime() 成员函数,并在主函数中,使用构造函数设置 时间为15时19分56秒并显示该时间。 构造函数也可以重载。关于重载的概念将在第 7章详细介绍,这里先看一个例子。 【例6.6】 构造函数重载定义示例。
【2021例/7/163 .8】 构造函数的调用。
21
6.3.2 析构函数 1.析构函数的特点 当对象创建时,会自动调用构造函数进行初始 化。当对象撤消时,也会自动调用析构函数进 行一些清理工作,如释放分配给对象的内存空 间等。与构造函数类似的是:析构函数也与类 同名,但在名字前有一个“~”符号,析构函数 也具有公有属性,也没有返回类型和返回值, 但析构函数不带参数,不能重载,所以析构函 数只有一个。 【例6.9】 析构函数程序举例。
26
6.4 对象数组与对象指针 6.4.1 对象数组 对象数组是指数组的每一个元素都是相同类型对象的 数组,也就是说,若一个类有若干个对象,把这一系 列的对象用一个数组来表示。对象数组的元素是对象, 不仅具有数据成员,而且还有成员函数。
对象数组的定义和普通数组的定义类似,一般格式如 下: 类名 数组名[第一维大小][第二维数组大小] 其中,类名是指该数组元素属于该类的对象,方括号 内的数组大小给出了某一维元素的个数。一维对象数 组只有一对方括号,二维对象数组要有两个方括号对, 等等。
25
普通构造函数在建立对象时被调用,而复制构造函数
在用已有对象初始化一个新对象时被调用。复制构造
函数被调用通常发生在以下3种情况:
(1)程序中需要新建一个对象并用一个类的对象

c++函数编译原理和成员函数的实现

c++函数编译原理和成员函数的实现

c++函数编译原理和成员函数的实现
c++函数编译原理是指编译器将c++源代码编译为可执行代码的过程,每个函数都有自己的编译原理。

编译原理包括从源代码到机器语言的d的过程,以及在程序空间中提供对函数的访问的过程。

c++中的函数可以分为全局函数、成员函数和静态成员函数。

成员函数是定义在特定类的作用域内的函数,它们可以访问类的所有成员变量。

而全局函数则不属于任何类,只是在全局作用域内定义的函数。

在编译过程中,全局函数和静态成员函数可以在代码段区域空间进行编译,编译完成后连接器将可执行代码放置在相应的栈上,便于在运行时调用。

而成员函数的编译原理与此有些不同。

成员函数必须附加在特定的类的内存空间,在其内存空间中只有当前类定义的所有成员函数或成员变量,所有对对象成员变量的访问都需要先对对象点号运算符引用对象,然后访问成员变量,而成员函数就是在参数表上添加一个隐藏的this指针参数,使编译器有能力访问类中定义的成员变量,调用和执行成员函数。

从以上可以看出,全局函数和静态成员函数都可以在代码段空间编译,连接器将其放置在栈上,从而在运行时可以通过普通函数的调用来访问;而成员函数则必须附加在特定的类的内存空间,且编译器必须携带this指针来访问类定义的成员变量,调用成员函数。

C++运算符重载三种形式(成员函数,友元函数,普通函数)详解

C++运算符重载三种形式(成员函数,友元函数,普通函数)详解

C++运算符重载三种形式(成员函数,友元函数,普通函数)详解三种重载⽅式⾸先,介绍三种重载⽅式:1//作为成员函数重载(常见)2class Person{3 Private:4string name;5int age;6public:7 Person(const char* name, int age):name(name),age(age){}8bool operator<(const Person& b);910 };11bool Person::operator<(const Person& b)12 {13//作为成员函数时,*this即为左操作数a14 ...15 }1//作为友元函数重载2class Person{3private:4string name;5int age;6public:7 Person(const char* name, int age):name(name),age(age){}8 friend bool operator<(const Person& a,const Person& b);910 };11bool operator<(const Person& a,const Person& b)12 {13 ...14 }1//作为普通函数重载(不推荐)2class Person{3public://注意,重载运算符为普通函数时,使⽤到的类成员必须为public4string name;5int age;6public:7 Person(const char* name, int age):name(name),age(age){}89 };10bool operator<(const Person& a,const Person& b)11 {12 ...13 }作为成员函数重载先介绍第⼀种:bool Person::operator<(const Person& b),bool是函数返回类型,Person::只是指定了成员函数所属类名。

C语言中friend友元函数详细解析

C语言中friend友元函数详细解析

C语言中friend友元函数详细解析C语言中friend友元函数详细解析友元函数是可以直接访问类的私有成员的非成员函数。

它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend。

我们已知道类具有封装和信息隐藏的特性。

只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。

非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。

另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。

为了解决上述问题,提出一种使用友元的方案。

友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。

友元不是成员函数,但是它可以访问类中的私有成员。

友元的作用在于提高程序的运行效率(即减少了类型检查和安全性检查等都需要的时间开销),但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。

友元函数的特点是能够访问类中的私有成员的非成员函数。

友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样。

复制代码代码如下:#include "cmath"#include "iostream"using namespace std;class Point{public:Point(double xx,double yy){x=xx;y=yy;}void GetXY();friend double Distance(Point &a,Point &b);protected:private:double x,y;};void Point::GetXY(){//cout<<"("<x<<","<y<<")"<<endl;cout<<"("<<x<<","<<y<<")"<<endl;}double Distance(Point &a,Point &b){double length;length=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); //它可以引用类中的私有成员return length;}int main(void){Point p1(3.0,4.0),p2(6.0,8.0);p1.GetXY(); //成员函数的调用方法,通过使用对象来调用p2.GetXY();double d = Distance(p1,p2); //友元函数的调用方法,同普通函数的调用一样,不要像成员函数那样调用cout<<d<<endl;system("pause");return 0;}说明:在该程序中的Point类中说明了一个友元函数Distance(),它在说明时前边加friend关键字,标识它不是成员函数,而是友元函数。

c课后习题解答

c课后习题解答

第6章;类和对象(一)练习题6判断题×1.使用class定义的类,其默认的访问权限是公有的,使用struct定义的类,其默认的访问权限是私有的。

×2.类中的成员函数都是公有的,数据成员都是私有的。

×3.定义在类体内的成员函数是内联函数,定义在类体外的成员函数不能是内联函数。

√4.类定义后,它的成员个数及名称就不会再被改变了。

×5.定义或说明对象时,系统会自动调用构造函数为创建的对象初始化。

如果类中没有定义任何构造函数时,就无法给定义的对象初始化。

√6.定义一个对象时,系统只为该对象的数据成员开辟内存空间,而成员函数是同类对象共享的。

√7.对象成员的表示方法与结构变量成员的表示方法相同。

√8.创建对象时系统自动调用相应的构造函数为对象初始化,没有相应的构造函数时,系统会自动生成。

√9.构造函数是一个其名与类名相同的特殊的成员函数。

×10.析构函数是一个函数体为空的成员函数。

√11.构造函数和析构函数都是系统自动调用的成员函数。

×12.构造函数和析构函数都可以重载。

√13.成员函数与一般函数一样可以重载、内联和设置参数的默认值。

×14.静态成员是指静态对象的成员。

×15.静态数据成员必须在构造函数的成员初始化列表中进行初始化。

√16.静态成员都可以使用类名加作用域运算符的方法来引用。

×17.静态成员函数中引用静态数据成员和非静态数据成员的方式是相同的。

√18.常成员指的是类体内使用const关键字说明的常数据成员和常成员函数。

×19.常数据成员在常成员函数中的值是不允许改变的,而在非常成员函数中是允许改变的。

√20.常对象需要引用常成员函数,而不能引用非常成员函数。

×21.常对象的数据成员都是常数据成员。

√22.友元函数是说明在类体内的非成员函数,它可以访问类中的所有成员。

×23.可以把一个一般函数说明为某类的友元函数,也可以将某类的成员函数说明为另类的友元函数。

友元运算符

友元运算符

友元运算符是一种在C++编程语言中用于实现两个类之间的友好关系的运算符。

它可以让一个类的成员函数或者变量访问另一个类的私有成员,以此来实现类的之间的数据共享和功能扩展。

友元运算符在C++编程中具有重要的作用,它可以提高代码的复用性和灵活性,使得类的设计更加模块化和清晰。

友元运算符可以分为以下三种类型:
1.友元函数:友元函数是一个类的成员函数或者全局函数,它可以访问另一
个类的私有成员。

友元函数的使用方法与普通函数相似,只需要在函数声明前加上友元关键字“friend”即可。

2.友元类:若类A需要去访问类B的非公成员,则A声明为B的友元类,那
么A就可以访问类B的非公有成员。

请注意,友元关系是单向的,只能从友元类访问宿主类,而不能反过来。

同时,友元会破坏封装性。

C++复习5大基础函数(析构函数、构造函数、内联函数、拷贝构造函数、友元函数)详解

C++复习5大基础函数(析构函数、构造函数、内联函数、拷贝构造函数、友元函数)详解

1、析构函数2、构造函数3、内联函数4、拷贝构造函数5、友元函数1、析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。

析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。

析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

2、构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。

构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回void。

构造函数可用于为某些成员变量设置初始值。

3、内联函数有时称作在线函数(inline)。

函数的调用是需要付出一定的时空开销的,因为系统在调用函数时,要保留现场,然后转入被调用函数去执行,调用完,再返回主调函数,此时再恢复现场,这些操作。

所谓“内联函数”就是将很简单的函数“内嵌”到调用他的程序代码中,只样做的目的是为了节约下原本函数调用时的时空开销。

但必须注意的是:作为内联函数,函数体必须十分简单,不能含有循环、条件、选择等复杂的结构,否则就不能做为内联函数了。

事实上,即便你没有指定函数为内联函数,有的编译系统也会自动将很简单的函数作为内联函数处理;而对于复杂的函数,即便你指定他为内联函数,系统也不会理会的。

内联函数也有一定的局限性。

就是函数中的执行代码不能太多了,如果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。

这样,内联函数就和普通函数执行效率一样了。

4、拷贝构造函数拷贝构造函数,又称复制构造函数。

复制构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量。

它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象.为什么需要拷贝构造函数?把参数传递给函数有三种方法,一种是传值,一种是传地址,一种是传引用。

传值与其他两种方式不同的地方在于当使用传值方式的时候,会在函数里面生成传递参数的一个副本,这个副本的内容是按位从原始参数那里复制过来的,两者的内容是相同的。

C++钱能

C++钱能

《C ++程序设计笔记(钱能主编)》第一部分基础编程(The Basic Programming)概述(Introduction)1、过程化程序设计(Procedural Programming):程序(Programs):=算法(Algorithms)+数据结构(Structures)(大型软件主要是Struct 之间的组合)描述问题只需3种基本控制语句:顺序、选择、循环。

每个模块,其内聚性(aggregation)越强,外联型(association)越小,则模块独立性越好。

2、对象化程序设计(Objectified Programming):程序(Programs):=算法(Algorithms)+抽象数据类型(ADS:Abstract Data Structure)。

这里的程序便可形成一种称之为类(Class)的对问题的描述;程序(Programs):=(对象(Object),对象(Object),…)。

这样就适应问题跨度更大,抽象层析更高,编程模块更加灵活高效。

第1章基本编程语句(Basic Programming Statements)1、C++的基本编程语句包括:说明语句、复制语句、表达式语句和过程控制语句,其中过程控制语句又包括:顺序语句、选择语句和循环语句。

注:这里,不考虑跳转语句(goto),goto的使用,不太适合过程化的思想。

2、在C/C++中,要将计算的结果保存在存储空间就必须指出存储空间的位置:在C/C++中,存储数据的名称有两种:①成为变量(或常量),是C\ C++内部数据类型定义而产生的。

②对象(或常对象),由程序员定义的类(Class)而产生的。

说明语句又分为:声明(Declarative)和定义(Definition)如果要在之前的程序中使用该程序之后定义的变量、对象或函数,则应该在程序之前对之后的部分进行声明,或者在其他文件中使用,亦如此。

变量的初始化与赋值。

c++笔记15静态成员和友元

c++笔记15静态成员和友元

静态成员的需要性静态成员的使用静态数据成员静态成员函数需要友元的原因友元的使用私有成员和保护成员提供了方便,但破坏了类的封装性和隐蔽性。

友元可以是一个函数,称为友元函数,也可以是一个类,称为友元类。

友元函数和友元类统称为友元。

一、静态成员的需要性类相当于一个数据类型,当说明一个某类的对象时,系统就为该对象分配一块内存单元来存放类中的所有成员。

但在某些应用中,需要程序中属于某个类的所有对象共享某个数据。

为此,一个解决的办法就是将所要共享的数据说明为全局变量,但这将破坏数据的封装性;较好的解决办法是将所要共享的数据说明为类的静态成员。

二、静态成员的使用C++中在说明类成员(数据成员和成员函数)时,使用了static关键字,则这类成员称为类的静态成员。

静态成员是所有对象公有的。

静态成员有静态数据成员和静态函数成员之分。

C++中,同一个类定义多个对象时,每个对象拥有各自的数据成员(不包括静态数据成员),而所有对象共享一份成员函数和一份静态数据成员。

静态数据成员是类的所有对象中共享的成员,而不是某个对象的成员,因此可以实现多个对象间的数据共享。

静态数据成员不属于任何对象,它不因对象的建立而产生,也不因对象的析构而删除,它是类定义的一部分, 所以使用静态数据成员不会破坏类的隐蔽性。

对静态数据成员的操作和一般数据成员一样,定义为私有的静态数据成员不能由外界访问。

静态数据成员可由任意访问权限许可的函数访问。

可以在类的成员函数中改变静态数据成员。

静态数据成员不从属于任何一个具体对象,所以必须对它初始化,且对静态数据成员的初始化不能在构造函数中进行。

类中用关键字static修饰的数据成员叫做静态数据成员。

说明一个静态数据成员的方法与说明一个一般静态变量一样,只不过前者是在一个类中说明。

静态数据成员的使用方法如下:1) 静态数据成员的定义与一般数据成员相似,但前面要加上static关键词。

2) 静态数据成员的初始化与一般数据成员不同,静态数据成员初始化的格式如下:<类型> <类名>::<静态数据成员>=<值>;int Student :: noOfStudents = 0;3)在引用静态数据成员时采用格式:<类名>::<静态数据成员>几点注意:⏹静态数据成员是类的一部分,静态数据成员的定义是类定义的一部分,将其放在类的内部实现部分中定义。

C++ friend友元函数和友元类

C++ friend友元函数和友元类

友元函数和友元类在实际开发中较少使用,想快速学习C++的读者可以跳过本节。

一个类中可以有public、protected、private 三种属性的成员,通过对象可以访问public 成员,只有本类中的函数可以访问本类的private 成员。

现在,我们来介绍一种例外情况——友元(friend)。

借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的private 成员。

fnend 的意思是朋友,或者说是好友,与好友的关系显然要比一般人亲密一些。

我们会对好朋友敞开心扉,倾诉自己的秘密,而对一般人会谨言慎行,潜意识里就自我保护。

在C++中,这种友好关系可以用friend 关键字指明,中文多译为“友元”,借助友元可以访问与其有好友关系的类中的私有成员。

如果你对“友元”这个名词不习惯,可以按原文friend 理解为朋友。

友元函数在当前类以外定义的、不属于当前类的函数也可以在类中声明,但要在前面加friend 关键字,这样就构成了友元函数。

友元函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数。

友元函数可以访问当前类中的所有成员,包括public、protected、private 属性的。

1) 将非成员函数声明为友元函数。

请大家直接看下面的例子:1.#include<iostream>ing namespace std;3.4.class Student{5.public:6.Student(char*name,int age,float score);7.public:8.friend void show(Student *pstu);//将show()声明为友元函数9.private:10.char*m_name;11.int m_age;12.float m_score;13.};14.15.Student::Student(char*name,int age,float score):m_name(name),m_age(age),m_score(score){}16.17.//非成员函数18.void show(Student *pstu){19.cout<<pstu->m_name<<"的年龄是"<<pstu->m_age<<",成绩是"<<pstu->m_score<<endl;20.}21.22.int main(){23.Student stu("小明",15,90.6);24.show(&stu);//调用友元函数25.Student *pstu =new Student("李磊",16,80.5);26.show(pstu);//调用友元函数27.28.return0;29.}运行结果:小明的年龄是15,成绩是90.6李磊的年龄是16,成绩是80.5show() 是一个全局范围内的非成员函数,它不属于任何类,它的作用是输出学生的信息。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第五章内容回顾
动态内存分配
堆 需要new和delete的原因 分配堆对象
拷贝构造函数
拷贝构造函数的概念 临时对象和无名对象 构造函数用于类型转换
1
第六章
静态成员与友元
2
预习检查
什么关键字标识了静态成员? 什么关键字标识了友元?
3
3
本章目标
静态成员 友元
17
类的作用域
类本身可被定义在三种作用域内: 1. 全局作用域。这是所谓全局类,绝大多数的C++类是定义在 该作用域中,我们在前面定义的所有类都是在全局作用域中。 2. 在另一个类的作用域中。这是所谓嵌套类,即一个类包含在 另一个类中。 3. 在一个块的局部作用域中。这是所谓局部类,该类完全被块 包含
int Student::noOfStudents =0; //静态数据成员在类外分配空间和初始化
8
6-1-3 静态数据成员
静态数据成员用得比较多的场合一般为:
用来保存流动变化的对象个数 作为一个标志,指示一个特定的动作是否发生 一个指向一个链表第一成员或最后一个成员的指针
9
6-1-3 静态数据成员
16
6-2 友元函数
整个类可以是另一个类的友元,该友元称为友 类
友类的每个成员函数都可访问另一个类中的保护或私有数据 成员
class Student { public: friend class Teacher;//友类 }; float gpa;
class Teacher { public: void assignGrades(Student& s); //赋成绩 void adjustHours(Student& s); //调整学时数 //… protected: void noOfStudents; Student* pList[100]; }
25
静态成员函数 class Directory{ public: static void setpath(char const *newpath); // 静态公有的函数 private: static char path [];// 静态字符串 }; char Directory::path [199] = "/usr/local"; //静态数据成员的初始化 void Directory::setpath(char const *newpath) // 静态函数 { strncpy(path, newpath, 199); } void main() { Directory::setpath("/etc"); // 通过类名调用setpath()成员函数 Directory dir; 26 setpath()成员函数 dir.setpath("/etc");//通过象调用 }
6-2 友元函数
友元的使用 在类里声明一个普通函数,标上关键字friend,就成了该类的友元, 可Байду номын сангаас访问该类的一切成员。 一个类的成员函数可以是另一个类的友元。
class Student { public: //... friend void Teacher:: assignGrades(Student); protected: Teacherx pT; int semesterHours; float gpa; };
12
6-2 友元函数
友元函数
需要友元的原因
• 有时候,普通函数需要直接访问一个类的保护或私有数据成员。 • 需要友元的另一个原因是为了方便重载操作符的使用。
友元函数不是成员函数,它是类的朋友,因而能够访问类的全部 成员。 在类的内部,只能声明它的函数原型,加上friend关键字
13
局部类
void Render (Image &image) { class ColorTable { //在方法内定义的局部类 public: ColorTable(void) { /* ... */ } AddEntry(int r, int g, int b) { /* ... */ } }; ColorTable colors; //在方法内定义的局部类对象 } 局部类不能在其局部作用域外访问 局部类必须完全定义在局部作用域内。所以,它的所有成员函数必须是内联的, 这就决定了局部类的成员函数
14
6-2 友元函数
友元函数提高效率的例子
Vector Multiply(Matrix&m,Vector&v) //友元定义 { if(m.szr!= v.sz) //直接访问保护数据 { cerr<<”badmultiplying MatrixwithVector./n"; exit(1); } Vector r(m.sz1); //直接访问保护数据 for(int i=0;i<m.sz1; i++) //直接访问保护数据 { r.V[i]=0; //直接访问保护数据 for(int j=0; j<m.szr;j++) //直接访问保护数据 r.V[i]+=m.m[i*m.szr+j]*v.v[j];//直接访问保护数据 } return r; 15 }
21
const成员函数
class Set { public: Set (){} bool Member(const int) const; void AddElem(const int); }; bool Set::Member (const int elem) const { } 非常量成员函数不能被常量成员对象调用,因为它可能企图修改常量的数 据成员: const Set s; s.AddElem(10); // 非法: AddElem不是常量成员函数 s.Member(10); // 正确 但构造函数和析构函数对这个规则例外,它们从不定义为常量成员,但 可被常量对象调用(被自动调用)。它们也能给常量的数据成员赋值,除非数 据成员本身是常量。
一个指向一个链表第一成员的指针 定义为static
#include <iostream> #include <string.h> class Student {
public: 避免了定义一个 Student(char* pName); 全局的pFirst ~Student(); protected: static Student* pFirst; Student* pNext; char name[40];
};
10
6-1-4 静态成员函数
静态成员函数
返回静态成员函数定义是类的内部实现,属于类定义的一部分。 它的定义位置与一般成员函数一样。 一个静态成员函数不与任何对象相联系,故不能对非静态成员进 行默认访问。
class Student { public: static int number( ) { //静态成员函数 return noOfStudents; } protected: char name[40]; static int noOfStudents; };
20
const成员函数
class Point { public: int GetX() const; //const成员函数 int GetY() const; //const成员函数 void SetPt (int, int); void OffsetPt (int, int); private: int xVal, yVal; }; int Point::GetY() const //const成员函数的实现 { return yVal; } const成员函数应该在函数原型说明和函数定义中都增加const限定:
11
6-1-4 静态成员函数
静态成员函数
#include<iostream.h> class Student { public: static char* sName() //静态成员函数是所有对象共享的 { cout<<noOfStudents<<endl; return name; //error哪个对象? } 一个静态成员函数不与任 protected: 何对象相联系,故不能对 char name[40]; 非静态成员进行默认访问 static int noOfStudents; };
22
const成员函数和const对象
const int i=1 ;//定义整型常量 const classA a(2);//定义常量对象 为了确保const对象的数据成员不会被改变,在C++中, const对象只能调用const成员函数。不能调用非const成员函数
23
静态数据成员 静态数据成员:类的静态数据成员仅创建和初始化一次,且在程序 开始执行的时候创建,然后被该类的所有对象共享 静态数据成员的访问方式是: 类名::静态数据成员名 class Test { public: static int public_int; private: static int private_int; }; int Test::public_int=145; void main() { printf("%d\n",Test::public_int); // 正确 } 注意:静态数据成员的初始化必须在类外
S2.noOfStudents
==
Student:: noOfStudents
7
6-1-2 静态成员使用
Student(char* pName ="no name") { cout <<"create one student\n"; strncpy(name, pName,40); name[39]='\0'; noOfStudents++; //静态成员:每创建一个对象,学生人数增1 cout <<noOfStudents <<endl; } ~Student() { cout <<"destruct one student\n"; noOfStudents--; //每析构一个对象,学生人数减1 cout <<noOfStudents <<endl; }
相关文档
最新文档