c中对象或其对象指针的赋值_第1页
c中对象或其对象指针的赋值_第2页
c中对象或其对象指针的赋值_第3页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、c+ 中对象或其对象指针的赋值C+ 中对象或其对象指针的赋值C+ 中成员函数的动态绑定:C+ 中要实现函数的动态绑定,必须在其基类中将函数声明为 virtual 且在子类中对函数加以实现。 然后用一个基类指针指向某一个子类对象,这样才会在函数调用时实现动态绑定。在 C+ 中,只有对象指针才有可能使用函数的动态绑定。所有对象实体所能够进行的操作都是静态绑定的。C+ 中对象或其指针的赋值操作:这是很容易混淆和出错的地方。 C+ 将指针暴露给用户,这样用户就有两种方式可以操作对象。通过对象本身操作或通过指针操作,但是这两种操作方式通常会带来不同的效果。但正因为这样的不同通常会给用户带来很大的困扰。这

2、里我们通过几种情况来对 C+ 中对象或对象指针的赋值操作进行总结。在总结之前,我们需要先明确C+ 中对象分配的机制。在C+ 中,对象可以被分配在静态数据区、栈空间或堆空间。被分配在静态数据区的对象在其定义时声明为 static,其在编译时刻被放入静态数据区。 栈空间的对象是通过对象的显式声明分配的。 堆中的对象则是通过 new 分配的。 C+ 的对象分配机制与Java 不一样, Java 里的所有对象都被分配在堆空间里。浅述 Java 中 OO 构造的实现一文简单叙述了Java 中对象的存储模型。 Java 中这种存储模型的设计借鉴于C+ 。C+也是采用同样的CIR 结构来记录类中的信息。在建

3、立一个类的对象时,C+ 编译器会为每个对象分配相应的空间来记录对象所属的类中的属性。而对对象所进行的操作,都是静态绑定的。1) 栈中对象的赋值:栈中对象的赋值采取深层拷贝的方式。考虑下面一个例子:#includeusing namespace std;class Fatherpublic:int a, b;Father()a = 0;b = 1;void func1()cout << a << " a in Father" << endl;void func2()cout << b << " b in F

4、ather" << endl;class Child: public Fatherpublic:int c;Child()a = 10;b = 11;c = 12;void func1()cout << a << " a in Child" << endl;void func2()cout << b << " b in Child" << endl;void func3()cout << c << " c in Child&qu

5、ot; << endl;int main()Father father;Child child;cout << "father addr is " << &father << endl;cout << "child addr is " << &child << endl;father.func1();father.func2();father = child;cout << "father addr is " <<

6、; &father << endl;cout << "child addr is " << &child << endl;father.func1();father.func2();return 0;在 main 函数中执行了 father=child 后, father 中所有的属性都被改变为 child 中对应属性的值, 而 father 中调用的方法还是类 Father 的方法。这说明一点,在对象被分配时,其所有的函数都已在静态时刻被绑定。即使变量在运行时被重新赋值,所改变的也只是对象的属性值。执行结果是

7、:father addr is 0x22ff48child addr is 0x22ff3c0 a in Father1 b in Fatherfather addr is 0x22ff48child addr is 0x22ff3c10 a in Father11 b in Father2) 堆中对象的赋值:堆中对象的赋值亦采用深层拷贝的方式。当把一个堆对象a赋给另一个堆对象b 时,并不是b 的指针指向a,而是将b中的属性值改变成为a 中的属性值。换言之,即使对象赋值发生,但是对象所处的内存位置并没有发生变化,指向这两个对象的指针也没有发生改变。如下例所示:#includeusing nam

8、espace std;class Fatherpublic:int a, b;Father()a = 0;b = 1;void func1()cout << a << " a in Father" << endl;void func2()cout << b << " b in Father" << endl;class Child: public Fatherpublic:int c;Child()a = 10;b = 11;c = 12;void func1()cout <&

9、lt; a << " a in Child" << endl;void func2()cout << b << " b in Child" << endl;void func3()cout << c << " c in Child" <func1();father->func2();*father = *child;cout func2();cout func3();return 0;*father=*child便是堆中对象的赋值。执行结果

10、为:father obj addr is 0x3e2d68child obj addr is 0x3e2d880 a in Father1 b in Fatherfather obj addr is 0x3e2d68child obj addr is 0x3e2d8810 a in Father11 b in Father=131074 c in Child我们可以看到执行前后,指针 father 和 child 的都没有发生改变。唯一改变的是father 所指向对象中的内容。在执行了 Child* child_1 = (Child*)father后,我们使用了一个Child*类型的指针指向了

11、father指针所指向对象的内存空间。这个Father 类型对象内存空间只记录了 a,b 两个属性的值,故在其访问属性c 时,便因为地址偏移访问到了这个内存空间之外,所以c 的值是一个不确定的整型数。这也是使用C+ 指针容易出现的错误之一。3) 对象指针的赋值:对象的赋值尚好理解,重点问题在于对象指针之间的赋值。到底是指针所指向对象的内容被改变,还是指针本身转向指向了另一个对象呢?从赋值这个操作本身的意义来看,是后者。 C+ 也是这样做的。当一个指针被赋成另一个指针后,这两个指针将指向相同的对象。但是,我们要讨论最重要的问题在于一个对象指针被赋值成另一个对象指针后,它所调用的函数究竟是原来类中

12、定义的函数还是新指向的对象对应的函数呢?考虑下面一段代码:#includeusing namespace std;class Fatherpublic:int a, b;Father()a = 0;b = 1;void func1()cout << a << " a in Father" << endl;void func2()cout << b << " b in Father" << endl;class Child: public Fatherpublic:int c;Chil

13、d()a = 10;b = 11;c = 12;void func1()cout << a << " a in Child" << endl;void func2()cout << b << " b in Child" << endl;void func3()cout << c << " c in Child" <func1();father->func2();father = child;cout func2();cout f

14、unc2 执行的是 Father 还是 Child 中的函数?如果大家对Java 比较熟悉,那么显然知道调用的是Child 中的方法,因为 Child 将 Father 中的 func1 与 func2 进行了重写(覆盖),在调用 father->func1 和 father->func2 时则发生了动态绑定。父类指针 father 指向了一个子类对象,所以在运行过程中理所当然地将被调用的方法绑定到子类中重写的方法上。但是所以C+ 也是如此么?答案是否定的。重申一遍,father->func1 和 father->func2 调用的是子类Java 中之Child 中的方

15、法,是因为发生了动态绑定!但是这段C+ 的程序没有任何动态绑定的发生,C+ 中发生动态绑定的前提是子类要实现基类中的virtual 函数。但是这段程序没有 virtual 函数,也就是说所有的函数调用都是静态绑定的。 所以无论 father 指针哪个对象,其在进行函数调用时调用的一定是在其定义时所声明的Father 类中的函数!换句话说,如果我们想让father 指针可以调用Child 中重写的方法,必须将基类Father 变成虚基类,其中的函数被改成virtual 函数。这样在使用father 指针指向Child 类型对象的时候调用的才是Child 中的函数。上面代码的执行结果为:father obj addr is 0x3e2d68ch

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论