第五部分思维导图PDF下载C++程序设计 第五章 特殊函数和成员

5.1 对象成员的初始化

可以在一个类中说明具有某个类的类型的数据成员,这些成员称为对象成员。形式如下

  • class A{
  • 类名1 成员名1;
  • 类名2 成员名2;
  • ……
  • 类名n 成员名n;
  • };

为了初始化对象成员,该类的构造函数需要调用对象成员所在类的构造函数,该类的构造函数定影如下:

  • A::A(参数表0):成员1(参数表1),成员2(参数标2),……,成员n(参数表n) {……//可选其他操作}

对象成员构造函数的调用顺序取决于这些对象成员在类中说明的顺序,与它们在成员初始化列表中给出的顺序无关。排在前面的对象成员先初始化。

  • 若一个对象X内包含2个对象成员A,B,那么构造和析构顺序为
    • 构造
      • A-B-X
    • 析构
      • X-B-A

当初始化const成员和引用成员时,必须通过成员初始化列表进行!

5.2 静态成员

静态成员

  • 概念
    • 如果类的数据成员或成员函数使用关键字static进行修饰,这样的成员称为静态数据成员或静态成员函数,统称为静态成员。
  • 静态数据成员
    • 静态数据成员只能说明一次,如果在类中仅对静态数据成员进行声明,则必须在文件作用域的某个地方进行定义(如类和主函数之间),在进行初始化时,必须进行成员名限定,如
      • int Test::x=25
    • 也可以直接在构造函数中使用类成员限定符对其初始化,如
      • Test(int a, int b) { Test::x = a; n = b; }
    • 静态数据成员通常被说明为私有的,通过定义共有的静态成员函数访问静态数据成员。

    • 类中的任何成员函数都可以访问静态成员
  • 静态成员函数

    • 静态成员函数没有this指针,所以静态成员函数只能通过对象名(或指向对象的指针)访问该对象的非静态成员。如
      • static void sfunc(Test&r, int a) { r.n = a; }
    • 注意:由于static不是函数类型中的一部分,所以在类声明之外定义静态成员函数时,不使用static。另类中定义的静态成员函数时内联的。

  • 要点

    • 除静态数据成员的初始化之外,静态成员遵循类的其他成员遵循的访问限制,虽然还没有建立对象,但静态成员已经存在
    • 尽量使用成员名限定符访问静态成员,比使用对象名访问静态成员要好,因为静态成员是类的成员而不是对象的成员。
      • 即 类名::成员名,非 对象名.成员名“ ::” > ” . “
  • 静态成员函数与一般成员函数的区别
    • 1、可以不指向某个具体的对象,只与类名连用。
    • 2、在没有建立对象之前,静态成员就已经存在。
    • 3、静态成员是类的成员,不是对象的成员。
    • 4、静态成员没有为该类的所有对象共享,他们被存储与一个共用内存中。
    • 5、没有this指针,所以除非显式地把指针传给他们,否则不能存取类的数据成员。
    • 6、静态成员函数不能被说明为虚函数。
    • 7、静态成员函数不能直接访问非静态函数。

静态对象

  • 不要混淆类的静态成员与静态对象!
    • 区别
      • 静态对象的构造函数在代码执行过程中,直到结束之前仅调用一次。
      • 静态对象的析构函数在整个程序退出之前被调用,同样也只调用一次。

5.3 友元函数

概念

  • 友元函数可以存取私有成员、共有成员和保护成员。
  • 友元函数可以是一个类或函数,尚未定义的类也可以作为友元。

1、类本身的友元函数

  • 在类内声明一个友元函数,但该友元函数并不是类的成员函数,可以在类外像普通函数那样定义这个函数。
    • 类内声明
      • friend double distances( Point&, Point& );
    • 类外定义
      • double distances( Point& a, Point& b ) { …… }
    • 也可以在类内声明时定义
      • friend double distances( Point& a, Point& b ) { …… }
  • 友元函数因为不是类的成员,所以没有this指针,在访问某一个类对象的成员时,必须使用对象名!而不能直接使用该类的成员名。
    • 即 对象名.成员名,不是 类名::成员名
  • 友元函数作用域的开始点在它的说明点,结束点和类的作用域相同。

  • 友元说明可以出现于类的私有或公有部分。
  • 优点

    • 1、友元函数可以直接访问对象的私有成员,因而省去调用类成员函数的开销。
    • 2、设计类时不必考虑好该类的各种可能的使用情况之后再设计类,而是可以根据需要,通过友元增加类的接口。
  • 缺点
    • 可访问私有成员,破坏了封装和数据隐藏,导致程序的可维护性差。

2、将成员函数用作友元

  • 一个类的成员函数(包括构造函数和析构函数)可以通过使用friend说明为另一个类的友元。如:
    • 在类 One中声明本类的成员函数,参数为Two类的引用
      • void func ( Two& )
    • 在类Two中声明类One的函数为友元函数,须使用限定符说明它的出处!
      • friend void One::func ( Two& );
    • 在两个类之外定义该友元函数,定义时同样需要使用限定符。
      • void One::func ( Two& r )
      • { r.y = x }

3、将一个类说明为另一个类的友元

  • 将一整个类说明为另一个类的友元,此时整个类的成员函数均具有友元函数的性能。
  • 声明友元关系简化为“ friend class 类名 ”,如
    • class Two { public friend class One;};
    • class One{…… ; void Display(……)};
    • void One::Display(……)
  • 友元声明与访问控制无关,在private处声明和public处声明没有太大区别。

  • 注意

    • 1、友元关系时不传递的,即当说明类A是类B的友元,类B又是类C的友元时,类A却不是类C的友元。
    • 2、友元关系不具有交换性,即类A为类B的友元时,类B不一定是类A的友元。
  • 目的
    • 使两个类系协同工作。

5.4 const 对象

1、常量数据成员

  • 声明
    • 常量数据成员
      • const int a;
    • 常引用
      • const int& a;
    • 静态常数据成员
      • const static int a;
  • 初始化
    • 常量数据成员,只能通过初始化列表来获得初值,类外初始化需要加类名
    • 常引用,只能通过初始化列表来获得初值,类外初始化需要加类名
    • 静态常数据成员,需要在类外初始化,类外初始化须加类名,即

2、常引用作为函数参数

  • 不允许函数修改对象的值,即不会破坏实参,如
    • void Display ( const double& r );

3、常对象

  • 概念
    • 对象名前使用const声明常对象,但声明时必须同时进行初始化,而且不能被更新。
  • 定义
    • 类名 const 对象名(参数表);
      • Class const a(2, 68);
  • 一个const对象只能访问const成员函数。

4、常成员函数

  • 声明

    • 类型标识符 函数名(参数列表) const;
  • 定义
    • 类内
      • 类型标识符 函数名(参数列表) const {……//函数体}
    • 类外
      • 类型标识符 类名::函数名(参数列表)const {……//函数体}
  • 调用时不需要const标识符

  • 目的

    • 防止函数改变数据成员的值
    • 如果一个类中两个函数同名,此时可定义一个const对象,用const函数来区分对重载函数的区分!因为const对象只能访问const成员函数
  • 注意:用const声明static成员函数没什么作用。C++中声明构造函数和析构函数时使用const关键词均是非法的。

5.5 数组和类

数组名代表数组首地址

指针在某些情况下可看成是数组

5.6 指向类成员函数的指针

概念

  • 指向类成员的指针用来访问某个特定类的对象中给定类型的任何成员它提供一种特殊的指针类型,指针指向类的成员,而不是指向该类的一个对象中该成员的一个实例,这种指针称为指向类成员的指针!

指向数据成员

指向成员函数

  • 假如类A中有个成员函数为int getx( int );
  • 声明

    • int ( A::*pointer )(int);
  • 指向
    • pointer = A::getx;
  • 使用
    • cout << (obj.*pointer)(3) << endl;

使用对象名或引用调用pointer所指向的函数时,使用运算符“ .* ”

使用指向对象的指针调用pointer所指向的成员函数时,使用运算符” ->* “

Written by:Vilen
最后修改日期:十一月 5, 2019

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。