`

《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版本中这种说法不对。数据的复制操作全由系统完成,并不调用任何实际上不存在的所谓拷贝构造函数。
以前提到,只当用户在类中定义了构造函数后,建立对象时系统才调用其构造函数。但尚须提及,当系统复制对象时,并不调用构造函数。因此时系统不使用任何实参来进行初始化,而只是简单地拷贝数值。

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

相关推荐

    C++学习笔记(快速入门C++)

    ### C++学习笔记知识点梳理 #### 一、开始 C++是一种高级编程语言,它是在C语言的基础上发展起来的,并且增加了面向对象编程的支持。学习C++的第一步是从熟悉其基本语法开始,然后逐渐深入理解面向对象编程的概念...

    c++学习笔记。干活!!!

    类可以包含静态数据成员和静态函数成员。 15. 友元:友元是C++中类的一个特殊功能,允许非成员函数访问类的私有或保护成员。 16. 继承:C++支持继承,子类继承父类的所有属性和行为,可以增加新的属性和行为。 17...

    C++-Primer阅读笔记

    C++ Primer 阅读笔记提供了许多关于C++编程的基础知识和重要概念。以下是这些笔记中的关键点: 1. **GNU 编译器**:C++的常用编译器是`g++`,用于编译C++源代码,如`...理解和掌握这些概念对于C++学习者来说非常重要。

    c++知识点总结笔记.docx

    C++是一种强大的编程语言,它融合了面向过程、面向对象和面向泛型的编程思想。以下是对这些知识点的详细说明: 一、面向过程编程的 C++ 在C++中,面向过程编程是基础,主要涉及以下几个方面: 1. 指针、数组和指针...

    自己的嵌入式C学习笔记

    空类虽然没有数据成员,但在大多数实现中,至少会占用1字节来存储对象的隐式`vptr`(虚函数表指针)。 `explicit`关键字用于防止隐式类型转换,确保类的构造函数只能被显式调用。 浅拷贝和深拷贝是拷贝构造函数和...

    c#学习笔记.txt

    结构与类很相似,都表示可以包含数据成员和函数成员的数据结构。与类不同的是,结构是值类型并且不需要堆分配。结构类型的变量直接包含结构的数据,而类类型的变量包含对数据的引用(该变量称为对象)。 struct 类型...

    C#学习笔记(c#重点整理).pdf

    它允许类作为所有数据类型的基底,使得每个实例都可以看作一个对象。然而,C#只支持单继承,即一个类只能有一个基类。 2. **.NET框架**:.NET框架包含了四个主要部分,包括虚拟操作系统(Virtual Operating System,...

    我的java笔记

    - **静态成员**:静态变量、静态方法、静态类,与类相关联而非对象。 - **Singleton模式**:确保一个类只有一个实例,并提供一个全局访问点。 - **final关键字**:用于限制变量、方法和类的修改。 - **抽象类**:...

    Arpack-arpack编译好的32位(x86)库文件(lib和dll)

    例如,可以创建`ArpackSolver`对象,并调用其成员函数进行计算。 6. **处理结果**:Arpack计算完成后,你会得到特征值和特征向量,可以根据需要进行进一步的分析或处理。 请注意,虽然这里提供的库文件是32位版本...

Global site tag (gtag.js) - Google Analytics