C ++ 中对象或其对象指针的赋值 c语言指针赋值

C++中对象或其对象指针的赋值

C++中成员函数的动态绑定:

C++中要实现函数的动态绑定,必须在其基类中将函数声明为virtual且在子类中对函数加以实现。然后用一个基类指针指向某一个子类对象,这样才会在函数调用时实现动态绑定。

在C++中,只有对象指针才有可能使用函数的动态绑定。所有对象实体所能够进行的操作都是静态绑定的。

C++中对象或其指针的赋值操作:

这是很容易混淆和出错的地方。C++将指针暴露给用户,这样用户就有两种方式可以操作对象。通过对象本身操作或通过指针操作,但是这两种操作方式通常会带来不同的效果。但正因为这样的不同通常会给用户带来很大的困扰。这里我们通过几种情况来对C++中对象或对象指针的赋值操作进行总结。

在总结之前,我们需要先明确C++中对象分配的机制。在C++中,对象可以被分配在静态数据区、栈空间或堆空间。被分配在静态数据区的对象在其定义时声明为static,其在编译时刻被放入静态数据区。栈空间的对象是通过对象的显式声明分配的。堆中的对象则是通过new分配的。C++的对象分配机制与Java不一样,Java里的所有对象都被分配在堆空间里。

《浅述Java中OO构造的实现》一文简单叙述了Java中对象的存储模型。Java中这种存储模型的设计借鉴于C++。C++也是采用同样的CIR结构来记录类中的信息。在建立一个类的对象时,C++编译器会为每个对象分配相应的空间来记录对象所属的类中的属性。而对对象所进行的操作,都是静态绑定的。

1)栈中对象的赋值:

栈中对象的赋值采取深层拷贝的方式。考虑下面一个例子:

#include

using namespace std;

class Father{

public:

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 Father{

public:

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" << 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 " << &father << endl;

cout << "child addr is " << &child << endl;

father.func1();

father.func2();

return 0;

}

在main函数中执行了father=child后,father中所有的属性都被改变为child中对应属性的值,而father中调用的方法还是类Father的方法。

这说明一点,在对象被分配时,其所有的函数都已在静态时刻被绑定。即使变量在运行时被重新赋值,所改变的也只是对象的属性值。

执行结果是:

father addr is 0x22ff48

child addr is 0x22ff3c

0 a in Father

1 b in Father

father addr is 0x22ff48

child addr is 0x22ff3c

10 a in Father

11 b in Father

2)堆中对象的赋值:

堆中对象的赋值亦采用深层拷贝的方式。当把一个堆对象a赋给另一个堆对象b时,并不是b的指针指向a,而是将b中的属性值改变成为a中的属性值。换言之,即使对象赋值发生,但是对象所处的内存位置并没有发生变化,指向这两个对象的指针也没有发生改变。如下例所示:

#include

using namespace std;

class Father{

public:

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 Father{

public:

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" << endl;

}

};

int main(){

Father* father = new Father();

Child* child = new Child();

cout << "father obj addr is " << father << endl;

cout << "child obj addr is " << child << endl;

father->func1();

father->func2();

*father = *child;

cout << "father obj addr is " << father << endl;

cout << "child obj addr is " << child << endl;;

father->func1();

father->func2();

cout << "===============================" << endl;

Child* child_1 = (Child*) father;

child_1->func3();

return 0;

}

*father=*child便是堆中对象的赋值。执行结果为:

father obj addr is 0x3e2d68

child obj addr is 0x3e2d88

0 a in Father

1 b in Father

father obj addr is 0x3e2d68

child obj addr is 0x3e2d88

10 a in Father

11 b in Father

===============================

131074 c in Child

我们可以看到执行前后,指针father和child的都没有发生改变。唯一改变的是father所指向对象中的内容。

在执行了Child* child_1 = (Child*) father后,我们使用了一个Child*类型的指针指向了father指针所指向对象的内存空间。这个Father类型对象内存空间只记录了a,b两个属性的值,故在其访问属性c时,便因为地址偏移访问到了这个内存空间之外,所以c的值是一个不确定的整型数。这也是使用C++指针容易出现的错误之一。

3)对象指针的赋值:

对象的赋值尚好理解,重点问题在于对象指针之间的赋值。到底是指针所指向对象的内容被改变,还是指针本身转向指向了另一个对象呢?

从赋值这个操作本身的意义来看,是后者。C++也是这样做的。当一个指针被赋成另一个指针后,这两个指针将指向相同的对象。

但是,我们要讨论最重要的问题在于一个对象指针被赋值成另一个对象指针后,它所调用的函数究竟是原来类中定义的函数还是新指向的对象对应的函数呢?

考虑下面一段代码:

#include

using namespace std;

class Father{

public:

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 Father{

public:

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" << endl;

}

};

int main(){

Father* father = new Father();

Child* child = new Child();

cout << "father obj addr is " << father << endl;

cout << "child obj addr is " << child << endl;

father->func1();

father->func2();

father = child;

cout << "father obj addr is " << father << endl;

cout << "child obj addr is " << child << endl;;

father->func1();

father->func2();

cout << "===============================" << endl;

Child* child_1 = (Child*) father;

child_1->func3();

return 0;

}

可以预见,在执行了father=child后,指针father和child指向了同一个Child类型的对象。但是问题是,现在father->func1和father->func2执行的是Father还是Child中的函数?

如果大家对Java比较熟悉,那么显然知道调用的是Child中的方法,因为Child将Father中的func1与func2进行了重写(覆盖),在调用father->func1和father->func2时则发生了动态绑定。父类指针father指向了一个子类对象,所以在运行过程中理所当然地将被调用的方法绑定到子类中重写的方法上。

但是C++也是如此么?答案是否定的。重申一遍,Java中之所以father->func1和father->func2调用的是子类Child中的方法,是因为发生了动态绑定!但是这段C++的程序没有任何动态绑定的发生,C++中发生动态绑定的前提是子类要实现基类中的virtual函数。但是这段程序没有virtual函数,也就是说所有的函数调用都是静态绑定的。所以无论father指针哪个对象,其在进行函数调用时调用的一定是在其定义时所声明的Father类中的函数!

换句话说,如果我们想让father指针可以调用Child中重写的方法,必须将基类Father变成虚基类,其中的函数被改成virtual函数。这样在使用father指针指向Child类型对象的时候调用的才是Child中的函数。

上面代码的执行结果为:

father obj addr is 0x3e2d68

child obj addr is 0x3e2d88

0 a in Father

1 b in Father

father obj addr is 0x3e2d88

child obj addr is 0x3e2d88

10 a in Father

11 b in Father

===============================

12 c in Child

由于father指针指向了一个Child类型的对象,虽然father无法直接访问到属性c,但是在做类型扩展后,可以通过地址偏移找到存储属性c的地址空间。从而访问到c的值12.

  

爱华网本文地址 » http://www.413yy.cn/a/25101011/77172.html

更多阅读

空气中主要污染物有哪些 空气的污染物有哪些

空气中主要污染物有哪些——简介在干洁的大气中,痕量气体的组成是微不足道的。但是在一定范围的大气中,出现了原来没有的微量物质,其数量和持续时间,都有可能对人、动物、植物及物品、材料产生不利影响和危害。当大气中污染物质的浓度达

Word中插入脚注和尾注的技巧 word如何脚注和尾注

Word中插入脚注和尾注的技巧——简介在编辑文章时,常常需要对一些从别的文章中引用的内容、名词或事件加注释。Word提供的插入脚注和尾注功能,可以在指定的文字处插入注释。脚注和尾注实现了这一功能唯一的区别是:脚注是放在每一页面的

梁中书是失去生辰纲的罪魁祸首 罪魁祸首 英文

梁中书是失去生辰纲的罪魁祸首杨志很郁闷梁中书让杨志押送生辰纲,千叮咛,万嘱咐,一路小心。杨志果然,做了很多努力,不过还是失去了生辰纲。那么到底谁该负主要责任,是杨志,老都管还是两个虞侯,或者另有其人。江湖以为梁中书应该负主要责任

C语言在K叉哈夫曼编码教学中的应用 c语言哈夫曼编码译码

摘 要:字符编码与信息压缩是计算机应用的重要研究课题,许多学者对此作了很多非常有价值的研究。文章简单分析了二叉哈夫曼树的构造及编码,通过比较三种构造三叉哈夫曼树的算法,提出了构造任意K叉哈夫曼树及K进制的最优前缀编码的算法,并

声明:《C ++ 中对象或其对象指针的赋值 c语言指针赋值》为网友艹秋风落叶分享!如侵犯到您的合法权益请联系我们删除