C++ 复制函数

C++ 复制函数

说道C++复制函数,大家也许并不陌生,就是类中的拷贝构造函数和赋值操作符,但是事实上也许我们一不小心就会忽略编译器所做的一些默认操作。引起晦涩的错误。下面分析几种场景:

一、场景一:全部默认

#include<stdio.h>
class base{
public:
	base(){}
	base(int dt):data(dt){}
	void get(){printf("base::data = %d\n",data);}
public:
	int data;
};
class derived:public base{
public:
	derived(){}
	derived(int dt,int ddt):base(dt),ddata(ddt){}
	void get()
	{
		base::get();
		printf("derived::ddata = %d\n",ddata);
	}
private:
	int ddata;
};
int main()
{
	derived da(1,5);
	derived db(2,10);
	da.get();
	db.get();

	da = db;
	da.get();
	db.get();

	derived dc(da);
	dc.get();

	base ba(da);
	ba.get();
	getchar();
}

结果:

如果在编译器中运行程序,我们知道,当调用复制函数是,除了派生类的成员被复制外,基类的成员也被复制。这是编译器的行为,当用户没有定义复制行为时,编译器就会主动提供一个默认版本同时在需要的时候悄悄的调用完成复制工作。

场景二、基类默认,派生类自定义

#include<stdio.h>
class base{
public:
	base(){}
	base(int dt):data(dt){}
	void get(){printf("base::data = %d\n",data);}
public:
	int data;
};
class derived:public base{
public:
	derived(){}
	derived(int dt,int ddt):base(dt),ddata(ddt){}
	derived(const derived&d)
	{
		printf("call derived::copy construct function.\n");
		ddata = d.ddata;
	}
	derived& operator=(const derived&d)
	{
		printf("call derived::operator= function.\n");
		ddata = d.ddata;
		return *this;
	}
	void get()
	{
		base::get();
		printf("derived::ddata = %d\n",ddata);
	}
private:
	int ddata;
};

结果:

从结果可以看出,当用户定义了复制函数时,一切默认行为就不会发生,即派生类中不会隐式调用基类的默认复制函数。

场景三、基类自定义,派生类默认

#include<stdio.h>
class base{
public:
	base(){}
	base(int dt):data(dt){}
	base(const base&b)
	{
		printf("call base::copy construct function.\n");
		data = b.data;
	}
	base& operator=(const base&d)
	{
		printf("call base::operator= function.\n");
		data = d.data;
		return *this;
	}
	void get(){printf("base::data = %d\n",data);}
public:
	int data;
};

class derived:public base{
public:
	derived(){}
	derived(int dt,int ddt):base(dt),ddata(ddt){}
	void get()
	{
		base::get();
		printf("derived::ddata = %d\n",ddata);
	}
private:
	int ddata;
};

结果:

从结果可以看出,当派生类没有显示定义复制函数时,那么他就会调用默认的复制函数,而默认复制函数会自动调用基类的复制函数。

场景四、基类派生类都自定义

#include<stdio.h>
class base{
public:
	base(){}
	base(int dt):data(dt){}
	base(const base&b)
	{
		printf("call base::copy construct function.\n");
		data = b.data;
	}
	base& operator=(const base&d)
	{
		printf("call base::operator= function.\n");
		data = d.data;
		return *this;
	}
	void get(){printf("base::data = %d\n",data);}
public:
	int data;
};

class derived:public base{
public:
	derived(){}
	derived(int dt,int ddt):base(dt),ddata(ddt){}
	derived(const derived&d):base(d)
	{
		printf("call derived::copy construct function.\n");
		ddata = d.ddata;
	}
	derived& operator=(const derived&d)
	{
		printf("call derived::operator= function.\n");
		ddata = d.ddata;
		return *this;
	}
	void get()
	{
		base::get();
		printf("derived::ddata = %d\n",ddata);
	}
private:
	int ddata;
};

结果:

从结果看出,只要定义了派生类的复制函数,那么就不会隐式调用基类的复制函数。

结论:只要派生类定义了复制函数,那么就不会隐式调用基类的复制函数,所以在这种情况下,我们必须显示调用基类的复制函数,以免造成复制的不完整。

下面给出显示调用的例子:

class base{
public:
	base(){}
	base(int dt):data(dt){}
	base(const base&b)
	{
		printf("call base::copy construct function.\n");
		data = b.data;
	}
	base& operator=(const base&d)
	{
		printf("call base::operator= function.\n");
		data = d.data;
		return *this;
	}
	void get(){printf("base::data = %d\n",data);}
public:
	int data;
};

class derived:public base{
public:
	derived(){}
	derived(int dt,int ddt):base(dt),ddata(ddt){}
	derived(const derived&d):base(d)
	{
		printf("call derived::copy construct function.\n");
		ddata = d.ddata;
	}
	derived& operator=(const derived&d)
	{
		printf("call derived::operator= function.\n");
		base::operator=(d);
		ddata = d.ddata;
		return *this;
	}
	void get()
	{
		base::get();
		printf("derived::ddata = %d\n",ddata);
	}
private:
	int ddata;
};

结果:

时间: 2024-10-29 04:28:01

C++ 复制函数的相关文章

第十七篇:复制控制( 上 ) --- 自定义复制函数

前言 若要将a对象复制给b对象,编译器应当做何工作?C++初学者也许会直接说” a对象的成员复制给b对象的成员 “.在很多情况下,这种说法正确,事实上C++会给类定义一个默认的复制函数,它所做的工作也正是如此.但,下面问题来了:如果类的成员当中有指针,这种做法还行吗?本文将对这个问题作出实例分析. 一个典型错误示例 下面这个代码示例用来检验前言中所提到的问题: 1 #include <iostream> 2 #include <cstdlib> 3 #include <fst

[笔记]C语言字符串比较函数,复制函数和拼接函数

1.字符串比较函数有两个,分别是memcmp()和strcmp(), memcmp(const char *s,const char *d,int n) 表示字符串s和d比较前n个字符,若字符长度小于n则会越界比较,用这个函数的时候要特别小心s和d在长度及要比较的字符个数. strcmp(const char *s,const char *d) 比上个函数少一个参数n,因为这个函数是以'\0'为比较结束标记的,如果某个字符串到达'\0'的位置,则结束比较,另外注意,两个字串s和d长度必须相等才可

C/C++字符串函数之复制函数

突然发现对字符串函数缺乏系统的了解,所以花了一点时间专门整理下,在此记录之,以方便自己及有需要的人使用. C/C++字符串函数的头文件:string.h 复制函数主要有4个,如下: 1.char * strcpy(char* destination,const char * source); 2.char* strncpy(char* destination,const char* source,size_t num); 3.void * memcpy(void* destination,con

第一篇博文,关于目录复制函数实现

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<sys/types.h>#include<fcntl.h>#include<unistd.h>#include<dirent.h>#include<sys/stat.h>char paths[1000],patht[1000],temp_paths[1000],temp_patht[100

java文件复制函数

在写代码中,经常会需要复制文件.这时候就可以把这些函数放到工具类里面. 下面是一个复制文件的函数: public class CopyFileUtil { private static String MESSAGE = ""; /** * 复制单个文件 * * @param srcFileName * 待复制的文件名 * @param descFileName * 目标文件名 * @param overlay * 如果目标文件存在,是否覆盖 * @return 如果复制成功返回true

通过编写字符复制函数strcpy函数学编程

首先我们先来开一下标准函数中的strcpy长什么样子 C语言标准库函数strcpy,把从src地址开始且含有'\0'结束符的字符串复制到以dest开始的地址空间. 原型声明:char *strcpy(char* dest, const char *src); 头文件:#include <string.h> 和 #include <stdio.h> 功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间 说明:src和dest所指内存区域不可以重叠且des

c++ 派生类的复制函数次序,及子父类兼容性

#include <iostream> using namespace std; class CFatherSum //父类Sum { public: CFatherSum(){cout<<"1,Default Constructing CFatherSum"<<endl;}//默认构造 CFatherSum(int iRec){cout<<"1,Constructing CFatherSum"<<iRec

C++类中的特殊成员函数-------复制构造函数

在C++中存在一个特殊函数,他就是复制构造函数,假如我们有类A,如果有A a;A b=a;   在这种情况下利用A类变量a来给同是A类变量的b来赋值,这个时候类会使用复制构造函数,如果我们不显式声明复制构造函数,那么类将会调用默认的复制构造函数.下面的代码说明了这一情况,如果我们将类StringBad中的复制构造函数StringBad(StringBad &)去掉,那么count最后输出的结果会为复制(count为静态变量用来记录类StringBad的对象个数). main.cpp #inclu

c语言——字符串变量、函数

//非A即B int IN(char *str) { char *str1="A"; printf("strcmp(str, str1) : %d\n", strcmp(str, str1)); if(strcmp(str,str1) ==0) { return 1; } else { return 0; } } 包含头文件 #inlcude<string.h> 字符串函数 字符串长度函数strlen strlen(arrayName);//返回 int