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