C++基础6:面向对象程序设计思想和类(上)

此博客是移动机器人知识体系下C++从入门到深入的内容,介绍了结构化和面向对象程序设计思想,详细阐述了类的定义、结构、成员访问控制等知识,还通过手机类、学生类等实战项目加深理解,同时讲解了类的作用域、this指针、静态成员、常成员等概念。

此专栏为移动机器人知识体系下的编程语言中的C{\rm C}C++从入门到深入的专栏,参考书籍:《深入浅出C{\rm C}C++》(马晓锐)和《从C{\rm C}CC{\rm C}C++精通面向对象编程》(曾凡锋等)。



6.面向对象程序设计思想和类
6.1 程序设计思想
6.1.1 结构化程序设计思想
  • 结构化程序设计思想运用的是面向过程的结构化程序设计方法(structured programming){\rm (structured\ programming)}(structured programming)

  • 结构化程序设计的基本思想:

    采用自顶向下、逐步求精的设计方法和单入口单出口的控制结构,一个复杂的问题可以划分为多个简单的问题组合;先将问题细化为由若干模块组成的层次结构,然后把每个模块的功能进一步细化,分解成一个个更小的子模块,直到分解为一个个程序的语句为止;

  • 结构化程序设计的优点:

    • 符合人分析问题的一般习惯和规律,容易理解、编写和维护;
    • 把一个问题逐步细化,从复杂到简单,逐个解决问题,分析问题是从整体到局部,解决问题是从局部到整体的过程;
  • 结构化程序设计的缺点:

    • 采用数据和操作分开的模式,一旦数据格式或结构发生变化,相应的操作函数就需要改变;
    • 无法对数据的安全性进行有效控制;
  • 结构化程序设计方法把解决问题的重点放在如何实现过程的细节方面,把数据和操作分开,以数据结构为核心,围绕功能实现或操作流程来设计程序;

  • 采用结构化程序设计方法设计出来的程序,基本形式是主模块与若干子模块的组合,即一个主程序加若干子程序,程序以函数为单位;

6.1.2 面向对象程序设计思想
  • 面向对象程序设计的基本思想:

    先将数据和对数据的操作方法集中存放在一个整体中,形成一个相互依存不可分割的整体,这个整体即为对相同类型的对象抽象出其共性而形成的类,类通过外部接口与外界发生联系,对象与对象之间通过消息进行通信;

  • 面向对象程序设计思想可以使程序模块间的关系变得简单,因为只有通过外部接口进行联系,且程序模块的相对独立性高,数据的安全性得到很好的保证;

  • 面向对象程序设计方法中,程序基本单位是类,类是C{\rm C}C++封装的基本单位,把数据和函数封装在一起;

  • 对象概念:

    • 对象是世界中的一个独立的单位,对象都有自己的特征,如静态特征和动态特征;
    • 对象的静态特征可以用某种数据描述,动态特征为其所表现的行为或具有的功能;
    • 面向对象程序设计思想中,对象是描述世界事物的一个实体,是构成程序的一个基本单位;对象由一组属性(数据)和一组行为(函数)构成,属性用来描述对象的静态特征,行为用来描述对象的动态特征;
  • 类概念:

    • 抽象和分类是面向对象程序设计的两个原则,抽象是具体事物描述的一个概括,抽象与具体是相对应的,分类的依据原则是抽象;
    • 面向对象的类是具有相同属性和行为的一组对象的集合,能为属于该集合的全部对象提供抽象的描述(包括属性和行为);
    • 类和对象的关系是抽象与具体的关系,一个属于某个类的对象称为该类的一个实例;
  • 封装概念:

    • 封装指将对象的属性和行为组合成一个独立的单元,并尽可能隐藏对象的内部细节;
    • 封装的两个特点:
      • 将对象的全部属性和行为组合在一起,形成一个不可分割的独立单元(类);
      • 对这个独立单元进行信息隐藏,使外部无法轻易获得单元中的信息,从而达到信息保护的目的,外部只有通过单元的外部接口与其发生联系;
  • 继承概念:

    • 某一个类的对象拥有另一个类的全部属性和行为,可以将这个类声明为另一个类的继承;
    • 如果一个一般类具有更高抽象的特征,则其可被继承性就高,如果相对于这个一般类,某个特殊类具备其所有特征,可以直接继承这个特殊性简化开发任务;
  • 多态概念:

    • 多态指在一般类中定义的属性或行为在被类继承后可以具有不同的数据类型或表现出不同的行为,可以使一个属性或行为在一般类和其所继承类中具有不同的含义或实现;
6.2 类
  • 类的定义和基本结构

    • 类的定义:类是一种用户自定义的数据类型,定义一个类后,可以声明一个类的变量,这个变量称为类的对象或实例,这个声明类变量的过程称为类的实例化,类包含类头和类体两部分;

    • 类的基本结构:

      // 类的基本结构:
      class 类名			// 类头;
      {
          ...				// 类体;
      };
      
    • 类头由关键字class{\rm class}class和类的名称组成,类体是类的实现声明部分,由一对大括号{}\{\}{}括起来,在最后需要加分号,命名类时加前缀"C{\rm C}C";

    • 类基本定义实例:

      // 定义一个手机类;
      class CMobilePhone{
          ...
      };
      
      // 定义一个手机类并实例化;
      class CMobilePhone{
          ...
      } myMobilePhone;
      
      // 定义一个书籍类;
      class CBook{
          ...
      };
      
      // 定义一个书籍类并实例化;
      class CBook{
          ...
      } myBook;
      
    • 在类的实现声明部分包含数据和函数,类中的数据称为数据成员,类中的函数称为成员函数,类的结构表示如下:

      class 类名
      {
          数据成员;
          数据成员;
          ...;
          成员函数;
          成员函数;
          ...;
      };
      
  • 数据成员

    • 类数据成员的声明语法格式:

      class CMobilePhone
      {
          string m_strPhoneName;					// 手机名称;
          string m_strPhoneType;					// 手机型号;
          float m_fLength,m_fWidth,m_fHeight;		// 手机长度、宽度、高度;
      };
      
    • 类数据成员的类型实例:

      enum MobilePhoneType {HUAWEI,XIAOMI,IPHONE};
      class CMobilePhone
      {
          string m_strPhoneName;					// 手机名称;
          MobilePhoneType m_ePhoneType;			// 手机型号;
          float m_fLength,m_fWidth,m_fHeight;		// 手机长度、宽度、高度;
          void (*pfApp)();						// 手机用户自安装应用程序指针;
      };
      
    • 除类中静态数据成员外,类的数据成员不能在类体内被显式初始化,类的数据成员通过类的构造函数进行初始化;

  • 成员函数

    • 成员函数用来操作数据成员的,成员函数的原型在类体中被声明,基本形式如下:

      class 类名
      {
          访问控制关键字 返回值类型 成员函数名(参数列表);		// 函数原型声明;
      };
      
    • 在类体中声明函数原型后,需要实现函数,一般在类体外进行成员函数的实现,形式如下:

      返回值类型 类名::成员函数名()
      {
          函数体;
      }
      
    • 类名后"::::::"为域解析操作符,用于在程序中来访问类域中声明的成员,成员函数必须在类中定义原型后再实现;

    • 如果成员函数实现简单,可以直接在类中实现,在类中称为内联成员函数,直接在成员函数声明处实现函数称为隐式声明,将inline{\rm inline}inline关键字放在函数声明处或放在类外的实现部分,称为显式声明,实例如下:

      // 需求:定义一个手机类,包括一个显示手机名、型号、尺寸的成员函数;
      class CMobilePhone
      {
          void SetPhoneName(string);
          void ShowPhoneName();
          void ShowPhoneType(){			// 隐式声明格式;
              cout << m_strPhoneType;
          };								// 相当于一个语句结束加分号;
          void ShowPhoneSize();
          
          /* 参数说明:
           * m_strPhoneName:手机名;
           * m_strPhoneType:手机型号;
           * m_fLength,m_fWidth,m_fHeight:手机尺寸;
          */
          string m_strPhoneName;
          string m_strPhoneType;
          float m_fLength,m_fWidth,m_fHeight;
      };
      
      // 标准的成员函数声明和定义格式;
      void CMobilePhone::ShowPhoneName()
      {
          cout << "Name of Phone:" << m_strPhoneName << endl;
      }
      
      // inline关键字显式声明格式;
      inline void CMobilePhone::ShowPhoneSize()
      {
          cout << "The phone size is:" << m_fLenght << "x" << m_fWidth << 
              "x" << m_fHeight << endl;
      }
      
      // inline关键字显式声明格式;
      inline void CMobilePhone::SetPhoneName(string strPhoneName)
      {
          m_strPhoneName = strPhoneName;
      }
      
      // 需求:定义一个学生信息类,包括显示学生的学号、身高、体重、年龄的成员函数;
      class CStudentInfo
      {
          string m_strStudentID;
          int m_intStudentHeight;
          int m_intStudentWeight;
          int m_intStudentAge;
          
          void ShowStudentID()
          {
              cout << "StudentID is:" << m_strStudentID << endl;
          };
          
          void ShowStudentHeight();
          void ShowStudentWeight();
          void ShowStudentAge();
      };
      
      void CStudentInfo::ShowStudentHeight()
      {
          cout << "Student height is:" << m_intStudentHeight << endl;
      }
      
      void CStudentInfo::ShowStudentWeight()
      {
          cout << "Student weight is:" << m_intStudentWeight << endl;
      }
      
      inline void CStudentInfo::ShowStudentAge()
      {
          cout << "Student age is:" << m_intStudentAge << endl;
      }
      
  • 类成员的访问控制:对类成员访问权限的控制是通过成员的访问控制属性实现,类的访问控制属性有三种:

    • 公有类型(public)({\rm public})(public):公有类型成员用关键字public{\rm public}public声明,公有类型的成员可以被类内部成员访问,也可以被类外部成员访问,对于外部成员来说,想访问类的成员,必须通过类的公有类型成员来访问,公有类型成员是外部访问类的唯一接口;
    • 私有类型(private)({\rm private})(private):私有类型成员用关键字private{\rm private}private声明,私有类型的成员只允许本类内部的成员函数访问,类外部的任何访问都被拒绝,这样可对类中的私有成员进行了有效的隐藏和保护;
    • 保护类型(protected)({\rm protected})(protected):保护类型成员用关键字protected{\rm protected}protected声明,保护类型和私有类型类似,区别于类继承过程中对新类的影响不同;
  • 类成员的访问控制属性声明语法格式实例:

    // 格式1:分开声明;
    
    class CMobilePhone
    {
        private string m_strPhoneName;
        private string m_strPhoneType;
        
        public void ShowPhoneName();
        public void ShowPhoneType();
    };
    
    // 格式2:相同控制属性的成员合并定义;
    class CMobilePhone
    {
        private:
        	string m_strPhoneName;
        	string m_strPhoneType;
        public:
        	void ShowPhoneName();
        	void SHowPhoneType();
    }
    
    // 需求:定义一个手机类,实现显示手机名、型号、重量的功能;
    class CMobilePhone
    {
        private:
        	string m_strPhoneName;		// 手机名称;
        	string m_strPhoneType;		// 手机型号;
        	float m_fPhoneWeight;		// 手机重量;
        public:
        	void ShowPhoneName();
        	void ShowPhoneType()
            {
                cout << "Type of Phone is:" << m_strPhoneType << endl;
            };
        	void ShowPhoneWeight();
    };
    
    void CMobilePhone::ShowPhoneName()
    {
        cout << "Name of phone is:" << m_strPhoneName << endl;
    }
    
    void CMobilePhone::ShowPhoneWeight()
    {
        cout << "Weight of Phone is:" << m_fPhoneWeight << endl;
    }
    
  • 类的实例和类成员访问

    • 类描述了一类事物的共同属性和行为,当把抽象的描述变成一个具体的事物时,此时成为了类的一个实例或称为对象(instance or object)({\rm instance\ or\ object})(instance or object)

    • 简单理解:类的定义类似一个产品的模具,通过这个模具可以生产出多个产品,这些产品即为实例;

    • 类是一种自定义的数据类型,类的实例也就是这个类的一个变量,声明实例的语法格式:

      // 1.一般的声明实例格式:
      类名 实例名1,实例名2,...;
      
      // 2.声明类的一个实例指针格式:
      类名 *实例指针名1,*实例指针名2,...;
      
      // 3.用实例地址或用new开辟一个新的实例来对实例指针赋值;
      CMobilePhone *pCMP_A1200;
      pCMP_A1200 = new pCMP_A1200();
      
      // 4.声明实例数组:
      CMobilePhone arrCMP_A1200[5];		// 实例数组;
      CMobilePhone *parrCMP_A1200[5];		// 实例指针数组;
      
    • 定义一个类时,系统不分配存储空间给这个类,因为这个类是虚拟的描述,不是真正的实体;当声明一个类的实例后,系统分配存储空间,此时系统需要分配空间用于存储类中的数据成员;

    • 声明多个实例时,操作任何一个实例都不会对其他实例造成影响,他们有各自的类数据成员的副本;

    • 声明类的实例后,就可以访问类的公有成员了,当声明的是类的实例(非实例指针)时,通过点(.)(.)(.)访问,当声明的是一个实例指针时,在指定了对象后,用成员访问操作符箭头(->)访问,格式如下:

      // 1.一般类实例
      实例.类成员;
      
      // 举例
      CMobilePhone HUAWEI;
      HUAWEI.ShowPhoneName();
      HUAWEI.ShowPhoneType();
      
      // 2.实例指针
      实例指针->类成员;
      
      // 举例
      CMobilePhone HUAWEI;
      CMobilePhone *pHUAWEI = &HUAWEI;
      pHUAWEI->ShowPhoneName();
      pHUAWEI->ShowPhoneType();
      
      // 3.对于实例数组或实例指针数组,访问其成员函数需要加上实例数组的下标;
      CMobilePhone arrHUAWEI[5];
      arrHUAWEI[1].ShowPhoneName();
      
      CMobilePhone *parrHUAWEI[5];
      parrHUAWEI[0] = new CMobilePhone();
      parrHUAWEI[0]->ShowPhoneName();
      
  • 手机类实战(MobilePhone)({\rm MobilePhone})(MobilePhone)项目:

    • 项目需求:编写一个手机类,实现设置和显示手机名、型号、尺寸的功能,并声明一个针对HUAWEI Mate 30{\rm HUAWEI\ Mate\ 30}HUAWEI Mate 30型号的实例,实现设置和显示手机名、型号、尺寸的功能。

    • 程序结构:

      • 程序主文件:main.cpp{\rm main.cpp}main.cpp
      • 手机类定义头文件:MobilePhone.h{\rm MobilePhone.h}MobilePhone.h
      • 手机类实现文件:MobilePhone.cpp{\rm MobilePhone.cpp}MobilePhone.cpp
    • 手机类定义头文件(MobilePhone.h)({\rm MobilePhone.h})(MobilePhone.h)

      /**
       * 作者:罗思维
       * 时间:2024/03/06
       * 描述:手机类定义头文件。
       */
      #include <string>
      #include <iostream>
      
      using namespace std;
      
      class CMobilePhone {
      	private:
      		string m_strPhoneName;					// 手机名称;
      		string m_strPhoneType;					// 手机型号;
      		float m_fLength, m_fWidth, m_fHeight;	// 手机尺寸;
      	public:
      		void SetPhoneName();
      		void SetPhoneType();
      		void SetPhoneSize();
      		void ShowPhoneName();
      		void ShowPhoneType();
      		void ShowPhoneSize();
      };
      
    • 手机类实现文件(MobilePhone.cpp)({\rm MobilePhone.cpp})(MobilePhone.cpp)

      /**
       * 作者:罗思维
       * 时间:2024/03/06
       * 描述:手机类实现文件。
       */
      #include "MobilePhone.h"
      
      void CMobilePhone::SetPhoneName() {
      	cout << "请输入手机名字:";
      	cin >> m_strPhoneName;
      }
      
      void CMobilePhone::SetPhoneType() {
      	cout << "请输入手机型号:";
      	cin >> m_strPhoneType;
      }
      
      void CMobilePhone::SetPhoneSize() {
      	cout << "请输入手机尺寸(长、宽、高):";
      	cin >> m_fLength >> m_fWidth >> m_fHeight;
      }
      
      void CMobilePhone::ShowPhoneName() {
      	cout << "Name of mobile phone:" << m_strPhoneName << endl;
      }
      
      void CMobilePhone::ShowPhoneType() {
      	cout << "Type of mobile phone:" << m_strPhoneType << endl;
      }
      
      void CMobilePhone::ShowPhoneSize() {
      	cout << "Size of mobile phone:" << m_fLength
      	     << "x" << m_fWidth << "x" << m_fHeight << endl;
      }
      
    • 程序主文件(main.cpp)({\rm main.cpp})(main.cpp)

      /**
       * 作者:罗思维
       * 时间:2024/03/06
       * 描述:手机类实现主文件。
       */
      
      #include "MobilePhone.h"
      
      int main() {
      	CMobilePhone HUAWEI_MATE30;			// 声明手机对象; 
      
      	HUAWEI_MATE30.SetPhoneName();
      	HUAWEI_MATE30.SetPhoneType();
      	HUAWEI_MATE30.SetPhoneSize();
      
      	cout << "如下是HUAWEI MATE30的相关信息:" << endl;
      
      	HUAWEI_MATE30.ShowPhoneName();
      	HUAWEI_MATE30.ShowPhoneType();
      	HUAWEI_MATE30.ShowPhoneSize();
      
      	return 0;
      }
      
  • 学生类实战(Student)({\rm Student})(Student)项目:

    • 项目需求:编写一个学生类,实现设置和显示学生姓名、学生班级、学生身高、学生体重的功能,声明一个学生的实例,实现设置和显示学生姓名、学生班级、学生身高、学生体重的功能。

    • 程序结构:

      • 程序主文件:main.cpp{\rm main.cpp}main.cpp
      • 学生类定义头文件:Student.h{\rm Student.h}Student.h
      • 学生类实现文件:Student.cpp{\rm Student.cpp}Student.cpp
    • 学生类定义头文件(Student.h)({\rm Student.h})(Student.h)

      /**
       * 作者:罗思维
       * 时间:2024/03/06
       * 描述:学生类实现头文件。
       */
      #include <string>
      #include <iostream>
      
      using namespace std;
      
      class CStudent {
      	private:
      		string m_strStudentName;		// 学生姓名; 
      		string m_strStudentClass;		// 学生班级; 
      		float m_fStudentHeight;			// 学生身高; 
      		float m_fStudentWeight;			// 学生体重; 
      	public:
      		void SetStudentName();
      		void SetStudentClass();
      		void SetStudentHeight();
      		void SetStudentWeight();
      
      		void ShowStudentName();
      		void ShowStudentClass();
      		void ShowStudentHeight();
      		void ShowStudentWeight();
      };
      
    • 学生类实现文件(Student.cpp)({\rm Student.cpp})(Student.cpp)

      /**
       * 作者:罗思维
       * 时间:2024/03/06
       * 描述:学生类实现文件。
       */
      
      #include "Student.h"
      
      void CStudent::SetStudentName() {
      	cout << "请输入学生姓名:";
      	cin >> m_strStudentName;
      }
      
      void CStudent::SetStudentClass() {
      	cout << "请输入学生班级:";
      	cin >> m_strStudentClass;
      }
      
      void CStudent::SetStudentHeight() {
      	cout << "请输入学生身高:";
      	cin >> m_fStudentHeight;
      }
      
      void CStudent::SetStudentWeight() {
      	cout << "请输入学生体重:";
      	cin >> m_fStudentWeight;
      }
      
      void CStudent::ShowStudentName() {
      	cout << "学生姓名为:" << m_strStudentName << endl;
      }
      
      void CStudent::ShowStudentClass() {
      	cout << "学生班级为:" << m_strStudentClass << endl;
      }
      
      void CStudent::ShowStudentHeight() {
      	cout << "学生身高为:" << m_fStudentHeight << "cm" << endl;
      }
      
      void CStudent::ShowStudentWeight() {
      	cout << "学生体重为:" << m_fStudentWeight << "Kg" << endl;
      }
      
    • 学生类主文件(main.cpp)({\rm main.cpp})(main.cpp)

      /**
       * 作者:罗思维
       * 时间:2024/03/06
       * 描述:手机类实现主文件。
       */
      #include "Student.h"
      
      int main() {
      	CStudent student;
      
      	student.SetStudentName();
      	student.SetStudentClass();
      	student.SetStudentHeight();
      	student.SetStudentWeight();
      
      	cout << endl;
      	cout << "学生的个人基本信息为:" << endl << endl;
      
      	student.ShowStudentName();
      	student.ShowStudentClass();
      	student.ShowStudentHeight();
      	student.ShowStudentWeight();
      
      	return 0;
      }
      
  • 类的作用域和对象的生存周期

    • 一个类是一个整体,类中所有的成员都位于类的作用域内,类的作用域指的是类定义和成员函数定义的范围,在类作用域中,类的成员函数可以无限制地访问自身类中的数据成员;

    • 对于类作用域外的其他类的数据成员和成员函数,访问类作用域内的成员受到限制,即封装的思想,把一个类的数据和行为封装起来,使得类的外部对该类的数据访问受到限制;

    • 类的成员函数内部出现与类成员相同的标识符,此时类中这个相同的标识符不再具有对这个成员函数的作用域,如:对于类CMobilePhone{\rm CMobilePhone}CMobilePhone,如果成员函数SetPhoneName{\rm SetPhoneName}SetPhoneName中出现了与数据成员m_strPhoneType{\rm m\_strPhoneType}m_strPhoneType相同名称的变量,则m_strPhoneType{\rm m\_strPhoneType}m_strPhoneType不在成员函数的作用域内;

    • 类作用域实例:

      void CMobilePhone::SetPhoneName()
      {
          /* 此成员函数中的局部变量m_strPhoneType与类中的数据成员CMobilePhone::m_strPhoneType
           * 具有相同的名称,则CMobilePhone::m_strPhoneType在成员函数中被屏蔽,不可见;
           */
          string m_strPhoneType;
          cin >> m_strPhoneType;		// 此时CMobilePhone::m_strPhoneType被隐藏;
          
          if(m_strPhoneType == "MATE30")
          {
              m_strPhoneName = "HUAWEI";
          }
      }
      
    • 利用点(.)(.)(.)、箭头(−->)、作用域运算符(::)(::)(::)访问类成员时,类成员具有类的作用域;

  • this{\rm this}this指针

    • this{\rm this}this指针是隐含在类中每一个成员函数中的特殊指针,用于指向正在被成员函数操作的对象;

    • this{\rm this}this指针工作原理:当通过一个类的实例调用成员函数时,系统会将该实例的地址赋予this{\rm this}this指针,再调用成员函数,因此,∗this*{\rm this}this代表此实例;

    • 程序中一般不直接使用this{\rm this}this来访问类的成员,除非是在变量的作用域中发生了冲突;

    • this{\rm this}this指针实例:

      void CMobilePhone::SetPhoneName()
      {
          string m_strPhoneType;						// CMobilePhone::m_strPhoneType被隐藏;
          cin >> m_strPhoneType;
          if(m_strPhoneType == "MATE30")
          {
              m_strPhoneName = "HUAWEI";
          }
          this->m_strPhoneType = m_strPhoneType;		// 利用this指针访问类中的数据成员;
      }
      
  • 静态成员

    • 类的静态数据成员和静态成员函数统称为类的静态成员,C{\rm C}C++是通过静态成员来实现类的属性和行为的;

    • 在一个类声明的多个实例中,每一个实例都维持着一份该类所有数据成员的副本;静态数据成员是一种特殊的数据成员,在类的所有实例中只有一个副本,由所有实例来共同维护和使用,达到数据在所有实例中的共享;

    • 静态数据成员采用static{\rm static}static关键字声明,形式如下:

      static 数据类型 数据成员名;
      
    • 静态数据成员实例(Sms)({\rm Sms})(Sms)项目:

      • 项目需求:编写一个手机短信息类,要求能够实现统计短信息总数的功能。

      • 程序主文件:main.cpp{\rm main.cpp}main.cpp

      • 短信息类定义的头文件:CSms.h{\rm CSms.h}CSms.h

      • 短信息类实现文件:CSms.cpp{\rm CSms.cpp}CSms.cpp

      • 短信息类定义头文件代码(CSms.h)({\rm CSms.h})(CSms.h)

        /**
         * 作者:罗思维
         * 时间:2024/03/07
         * 描述:手机短信息类定义头文件。
         */
        #include <iostream>
        #include <string>
        
        using namespace std;
        
        class CSms {
        	private:
        		/* 参数说明:
        		 * m_strSmsFrom:	信息来源;
        		 * m_strSmsTo:		信息发送对象;
        		 * m_strSmsTitle:	信息头部;
        		 * m_strSmsBody:	信息内容;
        		 * sm_nSmsTotal:	信息总数;
        		*/
        		string m_strSmsFrom;
        		string m_strSmsTo;
        		string m_strSmsTitle;
        		string m_strSmsBody;
        		static int sm_nSmsTotal;
        
        	public:
        		void ShowSmsTotal();
        		void SetSmsTotal();
        };
        
      • 短信息类实现文件代码(CSms.cpp)({\rm CSms.cpp})(CSms.cpp)

        /**
         * 作者:罗思维
         * 时间:2024/03/07
         * 描述:手机短信息类实现文件。
         */
        
        #include "CSms.h"
        
        void CSms::SetSmsTotal() {
        	sm_nSmsTotal++;
        }
        
        void CSms::ShowSmsTotal() {
        	cout << "手机短信息总数:" << sm_nSmsTotal << endl;
        }
        
      • 程序主文件代码(main.cpp)({\rm main.cpp})(main.cpp)

        /**
         * 作者:罗思维
         * 时间:2024/03/07
         * 描述:手机短信息总数统计主文件。
         */
        
        #include "CSms.h"
        
        int CSms::sm_nSmsTotal = 0;		// 类静态数据成员的定义性说明和初始化;
        
        int main() {
        	CSms sms1, sms2;
        
        	sms1.ShowSmsTotal();
        	sms2.ShowSmsTotal();
        
        	sms1.SetSmsTotal();		// 设定对象sms1中的短信息数量;
        	sms1.ShowSmsTotal();
        
        	sms2.ShowSmsTotal();
        	sms2.SetSmsTotal();		// 设定对象sms2中的短信息数量;
        
        	sms1.ShowSmsTotal();
        	sms2.ShowSmsTotal();
        
        	return 0;
        }
        
    • 静态数据成员具有静态生存期,不属于任何一个实例,只能通过类名访问,格式如下:

      类名::静态成员数据名
      
    • 类定义中,所声明的静态数据成员只是对它的引用性说明,必须在文件作用域内对其进行定义性说明和初始化,语法格式如下:

      数据类型 类名::静态成员数据名 = 初始值;
      
      // 举例
      int CSms::sm_nSmsTotal = 0;
      
  • 静态成员函数

    • 普通成员函数必须在声明实例后才能被访问,静态成员函数不需要类的实例就可以被直接访问;

    • 静态成员函数采用static{\rm static}static关键字来声明,语法格式如下:

      static 返回值类型 成员函数名(参数表);
      
    • 静态成员函数具有静态生存期,不属于任何一个实例,只能通过类名来访问,语法格式如下:

      类名::成员函数名
      
    • 静态成员函数实例(Csm2)({\rm Csm2})(Csm2)项目:

      • 项目需求:编写一个手机短信息类,利用静态成员函数取得短信息总数。

      • 程序主文件:main.cpp{\rm main.cpp}main.cpp

      • 短信息类的定义头文件:CSms.h{\rm CSms.h}CSms.h

      • 短信息类实现文件:CSms.cpp{\rm CSms.cpp}CSms.cpp

      • 短信息类定义头文件代码(CSms.h)({\rm CSms.h})(CSms.h)

        /**
         * 作者:罗思维
         * 时间:2024/03/07
         * 描述:手机短信息类定义头文件。
         */
        #include <iostream>
        #include <string>
        
        using namespace std;
        
        class CSms {
        	private:
        		/* 参数说明:
        		 * m_strSmsFrom:	信息来源;
        		 * m_strSmsTo:		信息发送对象;
        		 * m_strSmsTitle:	信息头部;
        		 * m_strSmsBody:	信息内容;
        		 * sm_nSmsTotal:	信息总数;
        		*/
        		string m_strSmsFrom;
        		string m_strSmsTo;
        		string m_strSmsTitle;
        		string m_strSmsBody;
        		static int sm_nSmsTotal;
        
        	public:
        		static void ShowSmsTotal();
        		void SetSmsTotal();
        };
        
      • 短信息类实现文件代码(CSms.cpp)({\rm CSms.cpp})(CSms.cpp)

        /**
         * 作者:罗思维
         * 时间:2024/03/07
         * 描述:手机短信息类实现文件。
         */
        
        #include "CSms.h"
        
        void CSms::SetSmsTotal() {
        	sm_nSmsTotal++;
        }
        
        void CSms::ShowSmsTotal() {
        	cout << "手机短信息总数:" << sm_nSmsTotal << endl;
        }
        
      • 程序主文件(main.cpp)({\rm main.cpp})(main.cpp)

        /**
         * 作者:罗思维
         * 时间:2024/03/07
         * 描述:手机短信息总数统计主文件。
         */
        #include "CSms.h"
        
        int CSms::sm_nSmsTotal = 0;		// 类静态数据成员的定义性说明和初始化; 
        
        int main() {
        	CSms sms;
        
        	CSms::ShowSmsTotal();		// 调用静态成员函数输出短信息总数; 
        	sms.SetSmsTotal();			// 对短信息数进行设定; 
        	
        	CSms::ShowSmsTotal();		 
        	sms.ShowSmsTotal();
        
        	return 0;
        }
        
    • 类的静态成员函数可以直接访问该类的静态数据成员和静态函数成员,不能直接访问非静态数据成员和非静态成员函数,非静态成员的访问需要通过实例进行;

    • 如果静态成员函数需要访问类的非静态成员,则需要通过参数取得实例名,再通过实例名进行访问;

  • 类的静态成员访问实例:

    class class_name
    {
        private:
        	int nVar;
        	static int snVar;
        public:
        	static void Func(class_name a);
        	static void Func2();
        	void Func3();
    };
    
    void class_name::Func(class_name a)
    {
        cout << nVar;		// 错误,直接引用类的非静态数据成员无效;
        Func3();			// 错误,直接引用类的非静态成员函数无效;
        
        cout << a.nVar;		// 正确,通过实例访问类的非静态数据成员;
        a.Func3();			// 正确,通过实例访问类的非静态成员函数;
        
        cout << snVar;		// 正确,通过实例访问类的静态数据成员;
        Func2();			// 正确,通过实例访问类的静态成员函数;
    }
    
  • 常成员

    • 利用const{\rm const}const修饰类的数据成员时,该数据成员为常数据成员,当修饰类的函数成员时,该数据为常函数成员;

    • 常数据成员通过const{\rm const}const关键字来声明,语法格式如下:

      const 数据类型 常数据成员名;
      
    • 在类中定义的常数据成员不能被任何一个函数改变,对常数据的初始化只能在类的构造函数中进行,初始化的方式是通过初始化列表;

  • 常成员实例(Sms2)({\rm Sms2})(Sms2)项目:

    • 项目需求:编写一个手机短信息类,定义一个用于表示信息最大长度的常数据成员。

    • 程序主文件:main.cpp{\rm main.cpp}main.cpp

    • 短信息类定义头文件:CSms.h{\rm CSms.h}CSms.h

    • 短信息类实现文件:CSms.cpp{\rm CSms.cpp}CSms.cpp

    • 短信息类定义头文件代码(CSms.h)({\rm CSms.h})(CSms.h)

      /**
       * 作者:罗思维
       * 时间:2024/03/08
       * 描述:手机短信息类定义头文件。
       */
      #include <iostream>
      #include <string>
      
      using namespace std;
      
      class CSms {
      	private:
      		string m_strSmsFrom;		// 信息来源; 
      		string m_strSmsTo;			// 信息发送对象; 
      		string m_strSmsTitle;		// 信息头部; 
      		string m_strSmsBody;		// 信息内容; 
      		static int sm_nSmsTotal;	// 信息总数; 
      		const int cMAX_MSG_LEN;		// 信息的最大长度; 
      	public:
      		CSms(int);					// 构造函数; 
      		void ShowMaxMsgLen();
      		static void ShowSmsTotal();
      };
      
    • 短信息类实现文件代码(CSms.cpp)({\rm CSms.cpp})(CSms.cpp)

      /**
       * 作者:罗思维
       * 时间:2024/03/08
       * 描述:手机短信息类实现文件。
       */
      
      #include "CSms.h"
      
      CSms::CSms(int nMaxMsgLen): cMAX_MSG_LEN(nMaxMsgLen) {
      }
      
      void CSms::ShowMaxMsgLen() {
      	cout << "cMAX_MSG_LEN:" << cMAX_MSG_LEN << endl;
      }
      
    • 程序主文件代码(main.cpp)({\rm main.cpp})(main.cpp)

      /**
       * 作者:罗思维
       * 时间:2024/03/08
       * 描述:手机短信息主文件。
       */
      #include "CSms.h"
      
      int main() {
      	CSms sms(140);
      	sms.ShowMaxMsgLen();
      
      	return 0;
      }
      
  • 常成员函数

    • const{\rm const}const关键字定义的函数为常成员函数,语法格式如下:

      数据类型 函数名(参数表) const;
      
      // 举例
      void ShowPhoneName() const;
      
    • 常成员函数的主要作用是禁止在函数体内更新实例的数据成员,在函数体内,一方面不能改变数据成员的值,另一方面不能调用该类中能改变数据成员的成员函数,即不能调用该类中其他非常成员函数;

  • 常成员函数(MobilePhone)({\rm MobilePhone})(MobilePhone)项目:

    • 项目需求:编写一个手机类,定义用于显示手机基本信息的常成员函数。

    • 程序结构:

      • 程序主文件:main.cpp{\rm main.cpp}main.cpp
      • 手机类定义头文件:MobilePhone.h{\rm MobilePhone.h}MobilePhone.h
      • 手机类实现文件:MobilePhone.cpp{\rm MobilePhone.cpp}MobilePhone.cpp
    • 程序主文件代码(main.cpp)({\rm main.cpp})(main.cpp)

      /**
       * 作者:罗思维
       * 时间:2024/03/11
       * 描述:手机相关信息主文件。
       */
      #include "MobilePhone.h"
      
      int main() {
      	CMobilePhone HUAWEI;
      
      	HUAWEI.SetPhoneName();
      	HUAWEI.SetPhoneType();
      	HUAWEI.SetPhoneSize();
      
      	cout << "HUAWEI Phone Information:" << endl;
      
      	HUAWEI.ShowPhoneName();
      	HUAWEI.ShowPhoneType();
      	HUAWEI.ShowPhoneSize();
      
      	return 0;
      }
      
    • 手机类定义头文件代码(MobilePhone.h)({\rm MobilePhone.h})(MobilePhone.h)

      /**
       * 作者:罗思维
       * 时间:2024/03/11
       * 描述:手机相关信息定义头文件。
       */
      #include <string>
      #include <iostream>
      
      using namespace std;
      
      class CMobilePhone{
      	private:
      		string m_strPhoneName;
      		string m_strPhoneType;
      		float m_fLength,m_fWidth,m_fHeight;
      	public:
      		void SetPhoneName();
      		void SetPhoneType();
      		void SetPhoneSize();
      		void ShowPhoneName() const;
      		void ShowPhoneType() const;
      		void ShowPhoneSize() const;
      };
      
    • 手机类实现文件代码(MobilePhone.cpp)({\rm MobilePhone.cpp})(MobilePhone.cpp)

      /**
       * 作者:罗思维
       * 时间:2024/03/11
       * 描述:手机相关信息实现文件。
       */
      #include "MobilePhone.h"
      
      void CMobilePhone::SetPhoneName() {
      	cout << "请输入手机名称:";
      	cin >> m_strPhoneName;
      }
      
      void CMobilePhone::SetPhoneType() {
      	cout << "请输入手机类型:";
      	cin >> m_strPhoneType;
      }
      
      void CMobilePhone::SetPhoneSize() {
      	cout << "请输入手机尺寸:";
      	cin >> m_fLength >> m_fWidth >> m_fHeight;
      }
      
      void CMobilePhone::ShowPhoneName() const {
      	cout << "m_strPhoneName:" << m_strPhoneName << endl;
      }
      
      void CMobilePhone::ShowPhoneType() const {
      	cout << "m_strPhoneType:" << m_strPhoneType << endl;
      }
      
      void CMobilePhone::ShowPhoneSize() const {
      	cout << "m_strPhoneSize:" << m_fLength << "x" << m_fWidth << "x" << m_fHeight << endl;
      }
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FUXI_Willard

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值