当前位置:C++技术网 > 资讯 > C++编程中的数据共享方法全面总结

C++编程中的数据共享方法全面总结

更新时间:2015-06-07 19:20:23浏览次数:1+次

    在做软件时,经常会需要进行数据共享。函数、类和对象之间经常会涉及到数据传递和共享的问题。处理得好可以让编程效率很高,逻辑很清楚,处理的不好,会让程序千丝万缕,缠缠绵绵无绝期,会让开发者头痛不已。由于数据共享带来的问题一般也很隐蔽,不会造成语法错误或者很少造成语法错误,主要造成的是逻辑错误,出现的错误是在数据显示上达不到自己的要求。
    C++语言因为有类的存在,因而和C语言的数据共享有一定的差别,并且相比C语言来说要更复杂些。初学者基本就对各部分的概念都模模糊糊的,更别说能都从整体上来把握。因为今天做软件设计到多个类之间进行数据传递和共享,因此借此机会将这部分的内容进行总结,分享给初学者,以助其能够有个整体的认识和高效的学习。如果你是高手,请自行绕过,如果你有兴趣,欢迎批评指正。
    数据共享,顾名思义,是在不同的模块之间共享数据。可以是对同一个数据轮流替换操作,或者是将数据进行传递。这里不讨论程序之间的数据共享。数据共享其实就是变量之间的共享和传递。共享指代变量的传递和变量的直接轮流操作,下面都直接使用共享一词。数据传递表示不改变原有数据变量,数据共享表示直接操作原始数据变量,可能改变原始变量。


    C++中需要共享的对象通常是函数之间、类之间、对象之间、函数与类之间、函数与对象之间和对象与类之间


    首先,函数之间的数据共享。我们从最简单的函数之间的数据共享说起。
    第一,函数之间如果需要进行数据共享,通过参数传递和返回值就可以做到。如果直接传递变量,那么就是对原来变量的一份复制,传递进函数之后对传递进去的变量的操作不影响原有的变量。这样可以做到数据的传递,对于占内存较小的变量可以使用这种方法。这样就进行了数据传递。如果要达到操作原有数据,实现轮流操作的功能,那么就可以通过返回值将操作后的值返回给调用函数去赋值给原始的值,这样就实现了轮流操作。其他函数也可以通过这种方法进行操作。这样就实现数据共享。
    第二,函数之间如果需要进行数据共享,还可以通过传递指针或者引用做到。指针这一类型,C语言和C++语言是一致的。通过传递原始变量的地址,给被调函数使用,就可以对原始数据进行操作,实现轮流操作,从而实现数据共享。如果只是想传递数据,而不想改变或者不能改变或者避免改变原始数据,也是可以通过指针进行数据操作,只要不执行赋值操作即可。但是为了防止原始数据被修改,使用const指针是一个不错的选择。const指针是一个指向常量的指针,本身的值即指向是可以改变的,但是不能通过指针改变被指向的变量。这样就可以很好的防止数据被修改。一旦有修改变量的意图,系统将会报错。而变量的直接传递是不会影响到原有变量的,但是为什么还要用指针来实现数据传递呢?因为在很多时候,比如传递一首歌曲或者一部电影,那么每个数据分片都比较大的,直接进行变量的传递,将会产生很大的系统开销,会占据很多内存,执行效率就很低。而使用指针只需要产生一个指针变量,指向原始的数据分片,不产生多余的一份,自然就节省内存,一方面减少内存的消耗,另一方面节省了传递数据的时间,效率非常高。这样既实现数据传递又能使效率很高,一般都这么做。在普通的变量传递时,如果要对原有多个变量进行修改,就不方便实现,当然不是不能实现。很多人都以为不能实现。比如说对于多个变量通过参数传递进被调函数,然后在函数内进行了修改,可以通过返回一个结构体将修改了的变量返回,然后逐个修改即可实现。但是这样做起来比较麻烦,这个结构体是局部变量,被调函数执行完后就要被释放掉,返回结构体的地址是不行的,这是其一;如果结构体中的数据量很多,自然效率就低了。所以这里只是提供实现的一种思路,真的要做的话,基本都采用指针。这是C语言和C++语言共同的话题。然而,在C++中,还有一种新类型,那就是引用。引用就是一个名称一个符号而已,因此,在声明引用时就要将这个符号与关联的变量关联起来,即声明时就要赋值,不能在声明后初始化。因为如果声明时不初始化,在声明后,在给引用进行赋值就不是初始化了,就形成不了关联这一功能,而是实现对变量的赋值,在C++的语法中就和原有的语法产生了冲突。假如允许声明后初始化,那么在后面的赋值中对于已经初始化的引用就是对关联的变量进行赋值,如果没有关联的引用,那就是初始化。那么这样一来,就使得语法变得复杂,编译器实现起来就复杂,开发者使用起来也容易出错,因为单单从一个赋值语句中谁知道那是初始化还是关联引用呢?所以C++语法就规定引用必须声明时进行初始化关联变量。关联后引用就是被关联的变量的别称,使用引用就是使用被关联的变量,改变引用的值就是改变被关联的变量的值。但是在传递引用时却不是传递变量本身,而是传递一个变量地址。传递之后进行操作还是如同操作原有变量一样的方法操作。因此,在C++中,对于数据的传递,基本就是用引用进行传递。当然其他方法都可以。如果不想对被引用关联的变量进行修改,可以使用const进行限定。那么这样也可以实现数据传递和共享。
    第三,通过全局变量实现数据共享。全局变量时相对的概念。如果全局变量在主函数之外,那么就是整个程序的全局变量。如果在主函数中,则相对于其他函数来说,也是相对来说的全局变量。但通常上我们都指的是主函数之外的变量。对于全局变量,不需要进行传递,直接共享就可以了。可以说非常方便,但是也是有问题的。全局变量容易产生混乱。在很多函数中直接操作全局变量,最后都不知道其值如何,可能产生逻辑错误。通常小程序总可以采用,但是大程序中不建议使用。


    其次,就是与类相关的共享了。这个C语言中是不具备的,面向对象的语言才有的特性。因为类有安全机制,权限访问控制机制,因此共享都是要通过权限的。这里讲的数据共享只要讲权限问题。操作数据和上面的函数之间的数据共享是一样的。
    第一,类数据成员的共享。类数据成员对于类内部的函数来说,权限控制是不起作用的。初学者对于类内部权限控制不起作用不太理解。就是在头文件中和实现文件的成员函数的定义中,可以直接操作数据成员。类中的实现函数,不可能用对象来访问的,本来就是在定义类,定义对象的生成的模型,此时不可能有对象的存在,所以用一个不存在的东西来引用自然也是不对的。所以说,类中的声明文件和实现文件的成员函数定义这两个部分无视类的权限控制,还不能通过对象进行数据访问,而是直接使用成员变量就可以了。成员变量和数据成员是同一个东西,只是两个名字而已。类内部的函数之间可以相互调用,成员变量在成员函数之间的共享如同上面说的函数之间的共享。上面是类内部的访问。然而在类外,情况大不相同了。用一个类声明一个对象,类中的成员变量都在对象中生成了一份,类只是一个模型,不保存这种不同的成员变量。既然叫做成员变量,就指的是对象的成员,自然是属于对象的。是对象的一个成员,自然也只能通过对象才能访问这个成员变量。要和对象打交道,那么此时权限控制就起作用了。这个对象允许外部的函数访问什么才能访问什么,不让访问的就访问不了。就拿一个人做比喻,一个人就是一个对象,这个人身上口袋里有各种东西,这些东西相当于对象的成员变量。公有权限就可以通过对象的点号操作符直接使用。这表示这个对象有意愿将这个东西让你使用。而保护的和私有的成员变量,是对象本身要特别保护的,即使你看见了,这个对象也不给你。要访问这类成员变量除非对象提供了访问的方法,比如这个人说你给他一个拥抱他就将苹果给你吃。他要是没有这个想法,你给再多的拥抱也无济于事。一句话,公有的可以直接通过对象加点号操作符使用,保护的和私有的不能通过对象加点号操作符使用,除非对象提供了访问方法,否则无法使用。有朋友可能会疑问,通过继承不是可以访问父类的成员变量吗?这似乎是很多幻觉造成的。继承是可以将父类的东西都继承过来了,记住,是继承过来了,而不是共享访问父类对象的成员变量。继承过来的东西是子类本身的东西,只是不需要子类再去努力创造了,与生俱来的,但是这不是父类对象的,而是从父类的东西按照父类这个模型造出来了而已。如果不继承,那么这些东西都要自己去造,白手起家,起点不一样,对于这句话,相信很多人会有很多的感触的。所以说,继承不是解决数据共享的问题,而是解决决定起点的问题。共享主要就是通过权限访问和前面提到的函数之间的数据共享来实现的。每个对象都有一套类的成员变量。因为类中的成员变量都只是一个模型,生成的对象都将这个模型造出一个东西自己使用。而成员函数就只是一个方法而已,这个方法不会变的,因此不需要每个对象都重新造一个,没必要,而对象的成员函数都是使用类的。在一定程度上来说,对象的成员函数只是类中声明的成员函数的一个地址而已。但是从逻辑来说,成员函数是属于对象的,外部函数不可以直接通过类来访问这些成员函数。成员变量在类中只是个模型,没有空间,因此不能够进行初始化。
    第二,类静态成员的共享。类的静态成员变量和静态成员函数比较特殊,它们属于类,在这个类中就已经为其分配了空间,因此可以给静态成员赋值,直接通过类作用域解析操作符使用这些静态的成员变量和成员函数。但是也是受制于权限控制的。在类内部访问都是无视权限控制的。但是在类外,如果静态成员变量是公有的就可以直接使用,如果不是则不可以直接使用。用对象加点号操作符也无法使用。在类的成员函数定义中可以无阻碍的使用。要使用这个有权限的类静态成员变量和成员函数需要类提供相应的函数来操作。这也就是权限控制保护数据的一个目的。类静态成员变量和成员函数只属于类,新生成的对象不包含这两个。
    第三,友元函数方式进行共享数据访问。这种方法也是初学者所不会使用的。友元函数不是类的成员函数,但是却有访问类中成员变量和成员函数的自由。因为类把友元函数当成朋友了,数据和方法共享,无障碍访问,这才叫做友元函数呀。友元函数定义中可以对象名加点号操作符访问类的数据。如果想让另外一个类无障碍的访问一个类的所有数据和成员函数,还不用通过类对象,还不想让这个类成为内部类,也可以让整个类成为类的友元类,方法同友元函数,那么友元类的所有成员函数就成为了友元函数了。

    最后,总结一下,第一部分说了函数之间的数据访问方式,第二部分又加上了面向对象的新的数据访问方式,第二部分含有第一部分的访问方式,只是额外说了权限访问的问题。