Skip to main content
  1. CPPs/

静态成员-友元函数-类的组合

·175 words

静态成员 #

静态数据成员 #

  • 在一个类中,若将一个数据成员说明为static,这种成员称为静态数据成员。
  • 与一般的数据成员不同,无论建立多少个类的对象,都只有一个静态数据的拷贝。从而实现了同一个类的不同对象之间的数据共享。

定义静态数据成员的格式如下: static 数据类型 数据成员名;

说明 #

  1. 静态数据成员的定义要加上关键字static ;
  2. 静态数据成员的初始化应在类声明之后, 定义对象之前,在类外单独进行。初始化格式为:

数据类型 类名::静态数据成员名 = 初始值

  1. 静态数据成员属于类,而不像普通数据成员那样属于某一对象。因此可以使用以下方式访问静态数据成员:

类名::静态数据成员名 如上例中的: Student::count和Student::sum

  1. 静态数据成员与静态变量一样, 在编译时创建并初始化。 它在该类的任何对象被建立之前就存在。因此, 公有的静态数据成员可以在对象定义之前被访问。对象定义后,也可以通过对象访问公有的静态数据成员,访问格式为:

对象名.静态数据成员名 对象指针->静态数据成员名

  1. 私有静态数据成员不能被类外部函数访问, 也不能用对象进行访问。
  2. C++支持静态数据成员的一个主要原因是可以不必使用全局变量。依赖于全局变量的类几乎都是违反面向对象程序设计的封装原理。

静态成员函数 #

  • 静态成员函数属于整个类, 是该类所有成员共享的成员函数。定义静态成员函数的格式如下:

static 返回类型 静态成员函数名(参数表);

  • 与静态数据成员类似,调用公有静态成员函数的一般格式有如下几种:

类名::静态成员函数名(实参表) 对象. 静态成员函数名(实参表) 对象指针->静态成员函数名(实参表)

说明 #

  1. 一般情况下,静态成员函数主要用来访问全局变量or同一类中的静态数据成员
  2. 私有静态成员函数不能被类外部函数和对象访问
  3. 静态成员函数可在建立任何对象之前处理静态数据成员,普通成员函数则不能
  4. 编译系统将静态成员函数限定为内部连接,也就是与现行文件相连接的其它文件中的同名函数不会与该函数冲突(因编译器而异)
  5. 在一般的成员函数中都隐含一个this指针, 用来指向对象本身, 而静态成员函数则没有this指针
  6. 静态成员函数一般不访问类中的非静态成员。若确实需要,静态成员函数只能通过对象名(或指向对象的指针)访问非静态成员
cout << “一只小猫的重量是:” << weight << “千克\n”;
		//不合法,weight是非静态数据成员
cout << “小猫的总重量是” << total_weight << “千克” << endl;
		//合法,total_weight是静态数据成员

若需要访问非静态数据成员,则只能通过对象名。 如:把display函数定义为静态成员函数时,可将对象的引用作为函数参数,将它定义为: static void display (Small_cat &w) cout « “这只小猫的重量是:” « w.weight « “千克\n”;

友元 #

友元函数 #

  • 将非成员函数声明为友元函数

友元函数不是当前类的成员函数, 而是独立于当前类的外部函数, 但它可以访问该类的所有对象的成员, 包括私有成员、保护成员和公有成员。

说明 #

  1. 友元函数不是成员函数, 在类外部定义友元函数时不必在函数名前加上“类名::”。

  2. 友元函数不是类的成员,它需通过作为入口参数传递进来的对象名去访问引用该对象的数据成员。

cout << “女孩的姓名是:” << x.name;
		//合法
cout << “女孩的姓名是:” << name;
		//不合法
  1. 当一个函数需要访问多个类时,友元函数就显得非常重要。
  2. 使用友元函数虽然提高了效率, 但与面向对象的程序设计思想相背,应当谨慎使用。

将成员函数声明为友元函数 #

  • 一个类的成员函数也可以作为另一个类的友元,这种成员函数不仅可以访问自己所在类对象中的所有成员, 还可以访问friend声明语句所在类对象中的所有成员。这样能使两个类相互合作、协调工作,完成某一任务。

友元类 #

  • 一个类作为另一个类的友元
  1. 格式

friend 类名;

class Y{
    .....
};
class X{
    .....
    friend Y;
    .....
};
  1. 当类Y被说明为类X的友元时,类Y的所有成员函数都成为类X的友元函数。这就意味着:作为友元类Y中的所有成员函数都可以访问类X中的所有成员(包括私有成员)。
  2. 友元关系是单向的,不具备交换性
  3. 友元关系不具有传递性

类的组合 #

  1. 如有以下的组合类:
    class  X{
        类名1   对象成员名1;
        类名2   对象成员名2;
           …
        类名n   对象成员名n;
    };

则类X的构造函数的定义形式为;

X::X(对象成员所需的形参,本类成员形参):
   对象成员名1(形参表1),…,对象成员名n(形参表n)
{
   // …构造函数体
} 
  1. 如有以下的组合类

Student::Student(string name1, string stu_no1, float s1, float s2, float s3): score1(s1, s2, s3)

  • 构造函数调用顺序
  • 先调用内嵌对象的构造函数(按内嵌时的声明顺序,先声明者先构造)。然后调用本类的构造函数。(析构函数的调用顺序相反)
  • 对上面的代码段而言:先调用对象成员score1的构造函数,再执行类Student的构造函数