`

《C++学习笔记》对象间非静态数据成员的复制

    博客分类:
  • C++
阅读更多
===============================================

未完待续,转载时请表明出处:http://www.cofftech.com/thread-1394-1-1.html

欢迎大家跟帖讨论哈~~~~~
===============================================
如果在建立新对象时希望将同一类中原有对象内所有非静态数据的值都复制到新对象中,犹如:
int j=10;
int k=j; 或int k(j); 那样,
则C++系统本身能够完成此类简单操作。
[例1]系统为新对象复制非静态数据
#include <iostream.h>
#include <string.h>

class point {
       int a, b;
       char *ptr;
       int size;
       int arr[3];
public:
       point (int j, int k, char *s, int m)     {
a = j; b = k;
              size = strlen(s) + 1;
              ptr = new char[size];
              strcpy( ptr, s);           
              for (int x=0; x<3; x++)      arr[x] = x+m;
              cout<<"Cons"<<endl;            
}
       void delet() { delete [ ]ptr; }
       void show ( ){   
cout<<a<<' '<<b<<' ';     
              cout << ptr << ' ';
              for (int x=0; x<3; x++)      cout<<arr[x]<<' ';
              cout<<endl;       
}
};

void main()
{
       point p1(6, 9, "You", 2);
       p1.show( );
       point p2 = p1;
       p2.show( );
       point p3 (p2);
       p3.show( ); 
       p1.delet( );    // delete only once
}

/* Results:
Cons
6 9 You 2 3 4
6 9 You 2 3 4
6 9 You 2 3 4
*/
以上程序中,只在建立对象p1时调用了构造函数Cons,而在建立对象p2和p3时则不调用构造函数,只是直接将对象p1各数据成员的值复制到对象p2和p3内,从而将对象p2和p3初始化。运行结果显示,这三个对象的数据成员a、b、char*和arr[3]互相完全相同,复制成功。
由于程序只调用过一次构造函数,也即只调用一次new运算符,因此在程序结束时也只须调用一次delete运算符。据此,使用另外的函数如下:
void delet( ) { delete [ ]ptr; }
C++系统在将原有对象内所有非静态数据的值复制到新对象中时,对数据类型并无限制。不但有预定义类型,而且有用户自定义类型,例如类的对象。当对象中含有子对象时(此时该对象称为复合对象),C++系统仍能将原有对象内包括子对象在内的所有非静态数据的值复制到新对象中,见下例:
[例2] 系统为复合对象复制非静态数据。其中子类class point包含图形的端点坐标x和y,而复合类class figure还包括图形的尺寸dim。这些尺寸可用作立体图形例如立方体、立体圆等的尺寸参数。
#include <iostream.h>

class point
{
       int x;
       double y;
public:
       point (int j, double m)
              {     x = j;      y = m;  
                     cout<<"CONS-sub"<<endl;           }
       void sub_show( )
       {     cout<<"sub-object : "<<x<<" and "<<y<<endl;  }
};

class figure
{
       int dim;
       point sub_obj;           // sub_obj为子对象
public:
       figure (int a, int b, double d) : dim(a), sub_obj(b, d)       //将数据和 子对象初始化
       {     cout<<"CONS"<<endl;           }
       void show( ) {   
sub_obj.sub_show( );              //显示子对象
                                   cout<<"dim = "<<dim<<endl;
}
};

void main()
{
       figure obj1(123, 456, 98.76);
       cout<<"First object:"<<endl;
       obj1.show( );
       figure obj2 = obj1;
              //将对象obj1内所有非静态数据(包括子对象sub_obj)的值复制到对象obj2中
       cout<<"Second object:"<<endl;
       obj2.show( );
}
/* Results:
CONS-sub
CONS
First object:
sub-object : 456 and 98.76
dim = 123
Second object:
sub-object : 456 and 98.76
dim = 123
*/
以上程序中,建立对象objp1时,先后调用了子对象和主对象的构造函数。而在建立对象objp2时,只由系统将对象objp1(包括子对象中的)的非静态数据复制到对象objp2中,并未调用构造函数。
C++系统也能将一个对象内所有非静态数据的值复制到另一对象的子对象内,见下例:
[例3]系统将对象内非静态数据的值复制到另一对象的子对象内
#include <iostream.h>

class point           //用于建立子对象
{
       double x;
       double y;
public:
       point (int j=0, double m=0)
              {     x = j;      y = m;  
                     cout<<"CONS-sub"<<endl;           }
       void sub_show( )
       {     cout<<"子对象部分: "<<x<<" and "<<y<<endl;  }
};

class figure
{
public:
       figure (double d) : dim(d)      //将数据和子对象初始化
       {     cout<<"CONS_fig"<<endl;            }
       void show( ) {     sub_obj.sub_show( );        //显示子对象
                                   cout<<"复合对象部分: "<<dim<<endl;      }
       double dim;
       point sub_obj;           // sub_obj为子对象
};

void main()
{
       figure objf (135);              //建立复合对象objf,其子对象初始化为缺省值
       objf.show( );
       cout<<"对复合对象objf的子对象sub_obj赋值:";
       point objp (789, 123.456);      //建立对象objp并初始化
       objf.sub_obj = objp;
              //使用对象figp对复合对象objf的子对象sub_obj赋值
       objf.show( );
}
/* Results:
CONS-sub
CONS_fig
子对象部分: 0 and 0
复合对象部分: 135
CONS-sub
子对象部分: 789 and 123.456
复合对象部分: 135
*/
有些书上提到,这些数据的复制是由所谓拷贝构造函数完成的。至少在VC++ 6.0版本中这种说法不对。数据的复制操作全由系统完成,并不调用任何实际上不存在的所谓拷贝构造函数。
以前提到,只当用户在类中定义了构造函数后,建立对象时系统才调用其构造函数。但尚须提及,当系统复制对象时,并不调用构造函数。因此时系统不使用任何实参来进行初始化,而只是简单地拷贝数值。

可能会进一步提问:不同类的对象(不是子对象)之间如何复制数据?这较为复杂,需要依靠赋值运算符的重载功能,以后我们会讨论的。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics