C++中的类和数据抽象

  综述:类具有信息隐藏的属性,尽管类对象知道如何通过定义良好的接口与其他类对象通信,但是类通常不知道其他类的实现方法。

 

  1.类的提出

     结构的局限性

     a)结构不能包含自身的实例;

     b)结构可以包含指向另一个相同结构的指针,作为自引用结构;

     c)结构的定义在内存中不保留任何空间,而是生成一个用于声明变量的新数据类型;

     d)结构成员的访问:

        使用圆点操作符:通过对象变量名或者对象的引用访问;

        使用箭头操作符:使用对象指针访问;

     e)结构通常通过传值调用传递,要避免复制结构的开销,应按引用调用传递结构;  

     g)结构的缺憾:

        (1)结构的数据可能没有进行初始化;

        (2)程序可以直接访问结构的数据,结构成员可能会被赋予无效值;

        (3)如果struct的实现发生变化,所有使用该struct的程序都要相应改变;

        (4)结构不能作为一个整体打印,结构成员只能逐个进行访问或者打印。

 

  2.类的定义

        类=数据成员+成员函数,程序员可以根据需要定义新的类类型,这使C++语言具有较好的可扩展性。

        (1)成员访问说明符:

            public:在程序能够访问类对象的任何地方,都可以访问public之后,下一个说明符之前的数据成员或者函数成员;

            private:之后,下一个说明符之前的所有数据成员或者成员函数只能由该类的成员函数访问;

        (2)public成员函数供类的客户用于操作类的数据;

        (3)构造函数与类同名,用于类的数据成员的初始化;

            生成类的对象时,会自动调用该类的构造函数;

            一个类可以有多个构造函数,通过函数重载来实现;

            构造函数不指定任何返回类型;

            类的数据成员不能在类体中声明时初始化,而是用类的构造函数初始化,或者用set函数为其赋值。

         (4)析构函数在系统收回对象的内存之前清理每一个类对象,析构函数不带参数,因此不能够重载;

         (5)类定义包含类的数据成员和成员函数的声明,成员函数的声明就是在类体中定义成员函数的原型,而成员函数的定义在类的外部是比较好的编程习惯,尽管在类外部定义,但还是在类的作用域中,只有类的其他成员知道他的名字,否则需要通过类对象,类对象引用或者类对象指针进行引用;

         (6)如果在类定义中定义成员函数,该成员函数会自动成为内联函数,在类外部定义的函数可以通过inline显式指定为内联函数。定义内联函数可以提高性能,但是不易提高软件质量,因为客户程序可以看到函数的实现方法,并且如果内联函数的定义发生变化,必须重新编译代码,因此,只有最简单的成员函数和最稳定的成员函数可在类的头文件中定义;

         (7)类通常不需要从头开始建,可以从其他类的属性和行为中派生出来,这叫做继承;类可以包含其他类的对象,将其作为成员,这叫做复合;

         (8)对象只包含数据,对类名或者类的对象采用sizeof操作符时,只能得到类的数据的长度,编译器生成独立于所有类的对象的成员函数的副本,类的所有对象共享这唯一的成员函数副本,每个对象都有自己的数据副本,因为对象中的数据是不同的,函数代码不可修改,因而可供类的所有对象共享。

         (9)类的作用域:类的作用域=类的数据成员+类的成员函数,非成员函数在文件作用域中定义;

             类作用域中,类成员可以由该类的所有成员函数访问,在类的作用域之外可以通过句柄进行访问,可以是对象名,对象引用或者对象的指针;

             在成员函数中定义的变量具有函数作用域,只有该函数知道函数作用域,如果成员函数定义了与类作用域变量同名的另一个变量,则在函数作用域中,函数作用域的变量将隐藏类作用域的变量,要访问这一变量需要在变量名前面加上类名和作用域分辨符;

 

    3. 接口同实现方法的分离

            良好的软件工程的原则之一是实现接口与实现方法的分离,这样可以使程序更易于修改,类实现方法的改变不会对客户程序造成影响,只要对外提供的接口不变;

            (1)实现方法:类声明放在使用该类的任何客户的头文件中,形成类的public接口,将类的成员函数的定义放在源文件中,形成类的实现方法;类客户需要调用成员函数,不需要访问类的源代码,但是,客户需要连接类的对象代码;

             缺憾:内联函数包含在类的定义中,private成员包含在头文件中,尽管客户不能访问private成员,但是能够看到它们;

            类接口的关键信息放在头文件中,只用于类内部使用且客户不需要的信息应放在不发布的源文件中;

 

    4.控制对成员的访问

            类的默认访问模式是private,类的客户不能访问类的private成员和public成员函数的定义;

            结构成员的默认访问方式是public

            客户程序可以通过类的成员函数或者友元函数访问或者修改类的private数据成员,设计这些函数时应确保数据的完整性。

 

    5.析构函数

        删除对象时会调用类的析构函数,程序执行离开初始化类对象的作用域时对类对象执行的自动操作;

        析构函数本身并不删除类的对象,而是在系统回收对象内存之前执行的结束清理工作,以便内存可重复用于保存新的对象;

 

    6.构造函数和析构函数的调用顺序

        构造函数和析构函数都是自动调用的,这些函数的调用顺序由执行过程进入和离开对象实例化的作用域的顺序决定;

        a)全局范围内定义的对象的构造函数在文件中其他函数(包括main)开始执行前调用,当main中止或调用exit函数,调用相应的析构函数,abort中止程序时,不调用析构函数;

        b)程序执行到声明对象时,调用局部对象的构造函数,对象离开作用域(机离开声明对象的块时),调用相应的析构函数,调用exit和abort函数中止程序,可以不调用析构函数;

        c)程序执行到静态局部变量声明是,只调用静态局部对象的构造函数一次,main中止或调用exit函数时,调用析构函数,abort中止程序可以不调用相应的析构函数;

 

   

在上述代码中的调用顺序为:

construction 1;

construction 2;

construction 3;

construction 5;

construction 6;

construction 7;

destruction 7;

destruction 5;

construction 4;

destruction 4;

destruction 2;

destruction 6;

destruction 3;

destruction 1;

 

7.不要让类的public成员函数返回对该类private数据成员的非常量引用,这种引用会破坏类的封装

8.赋值操作符可以将一个对象赋给另一个类型相同的对象,默认通过成员复制进行,但如果数据成员包含动态分配内存的对象,可能会引发严重的问题;

9.和内置类型对象类似,用户自定义类的对象可以作为函数参数进行传递并从函数返回,这种传递和返回默认按传值调用进行,即传递和返回对象的副本,这样安全性比较高,被调函数无法访问原对象,但是如果要复制大的对象,性能会有所降低;

  对象按引用传递时可以按指针或对象引用传递,但安全性较低,因为被调函数能够访问原始对象,按常量引用既安全,又有性能上的优势;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值