分享
 
 
 

消除拷贝构造函数和“模板式拷贝构造函数”中的冗余代码

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

写完了《当心编译器生成的隐含成员函数》一文,总是对在两个不同的函数中使用相同的代码(只是参数类型不同)做相同的事耿耿于怀。在《C++ STL中文版》中的quto_ptr中的代码很简单,但很多时候我们要做的并不是这么简单的。代码冗余的危害不只是让你把相同的代码多写一遍,而且会给你的修改带来麻烦——你很容易修改了一个实现而忘记了另一个。赋值操作符的问题很好解决,可以简单地用一个模板成员函数来完成实际的赋值操作,然后在你的拷贝赋值操作符和模板形式的赋值操作符的实现中都只是简单地调用这个成员函数(就是下面的方法一);而拷贝构造函数就相对复杂了一些,因为出于某种理由我们可能需要在成员初始化表中对成员进行初始化而不是在代码中注一,而普通的成员函数是不能使用这种方法的。下面列出几种解决方法,供大家参考:

方法一:使用模板成员函数完成构造。

就是说使用一个模板成员函数来完成需要在拷贝构造函数中可以放在函数体中的代码部分,然后在拷贝构造函数和“伪拷贝构造函数”注二的实现代码中都只是简单地调用它。代码示意如下:

template <typename T>

class smart_ptr

{

T* ptr_data;

template <typename U>

void DoCopyConstruct(const smart_ptr<U> &)

{

ptr_data = Source.get_ptr();

//其它处理

}

public:

T* get_ptr()const{return ptr_data;}

smart_ptr(const smart_ptr<T>& Source){DoCopyConstruct(Source);}

template <typename U>

smart_ptr(const smart_ptr<U>& Source){DoCopyConstruct(Source);}

};

这种方法的缺点在于:当有需要在构造函数的成员初始化列表中进行初始化的成员存在时,对这些成员的初始化仍然要在两个构造函数的成员初始化表中各写一遍。不过,一般情况下成员初始化表中的代码都很简单,改动相对较少,所以这里的代码危害也就不是很大。

方法二:使用一个成员对象封装数据。

事实上,我们对一个对象进行构造实质就是对数据进行初始化,我们可以把数据用一个类封装起来成为一个成员对象,然后在构造函数中在成员初始化表中对这个对象进行初始化。而这时我们在把“伪拷贝构造函数”转移到这个数据类中时可以对它的参数类型进行修改,使它不受拷贝构造函数的影响,比如加一个匿名参数,更简单的方法是把参数类型从引用改为指针。代码示意如下:

template <typename T>

class data

{

data(const data<T> &);//这个构造函数是不被调用的,写成私有以免误被调用。

public:

T* ptr;

template <typename U>

data(const data<U> * Source):

ptr(Source->ptr)

{

//其它处理

}

};

template <typename T>

class smart_ptr

{

data<T> ptr_data;

public:

const data<T>& get_data()const {return ptr_data;}

smart_ptr(const smart_ptr<T>& Source):ptr_data(&Source.get_data()){}

template <typename U>

smart_ptr(const smart_ptr<U>& Source):ptr_data(&Source.get_data()){}

};

方法三:把拷贝操作放到基类中实现。

就是说,为你的类写一个基类,在基类中写一个不受拷贝构造函数影响的模板构造函数,在衍生类中调用这个构造函数。这种方法的原理基本上是和方法二是一样的,只是把组合变成了继承。代码示意如下:

template <typename T>

class smart_ptr_base

{

smart_ptr_base(const smart_ptr_base<T> &);//这个构造函数是不被调用的,写成私有以免误被调用。

protected:

T* ptr;

public:

T* get_ptr()const {return ptr}

template <typename U>

data(const smart_ptr_base<U> * Source):

ptr(Source->get_ptr())

{

//其它处理

}

};

template <typename T>

class smart_ptr: protected smart_ptr_base<T>

{

public:

smart_ptr(const smart_ptr<T>& Source):smart_ptr_base(&Source){}

template <typename U>

smart_ptr(const smart_ptr<U>& Source):smart_ptr_base(&Source){}

};

上面只列出了三种方法,但我想解决一个问题的方法是很多的,一定还存在其它方法,如果大家想到了,我希望能够告诉我或补充在这里,由衷感谢。

此外,上面的示意代码只是针对本文提出的问题的,并没有考虑其它因素,在应用时不能简单照般,还要根据具体情况进行修改。

注一:这种理由可以找到很多,比如常量成员的存在、成员无缺省(无参数的)构造函数、效率原因等。

注二:就是题目中的“模板式拷贝构造函数”,我实在不知道该叫它什么名字了,也许称作“模板式拷贝构造函数”更清晰一些,但容易让人误认为它是一个真正的拷贝构造函数,因此在本文中就把它称为“伪拷贝构造函数”

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有