Code Bye

设计模式–装饰模式 的析构问题

	Person *person = new Person("淼淼");
	DecorateA *deA = new DecorateA();
	DecorateB *deB = new DecorateB();
	DecorateC *deC = new DecorateC();
	
	deA->setComponent(person);
	deB->setComponent(deA);
	deC->setComponent(deB);
	deC->show();

代码如上,那deA  deB  deC 还有person,应该这么来delete了?
假如想下面这样delete的话,会出错:
delete deC;
delete deB;
delete deA;
delete person;
倒过来也会的、
问一下各位,想这种情况,应该怎么析构了?
源码 可以参照这里:
https://git.oschina.net/wuxiangfeng/DesignModeStudy.git

解决方案:15分
和调用子对象构造/习惯函数一样,一般建议倒着来。
但是lz的很特殊,肯定没有处理好引用关系。
最基本的先把引用关系去除再delete就没问题了。
但是lz的代码本身问题非常大。随便看了一个:
DecorateB::~DecorateB(void)
{
	if(component != nullptr)
	{
		delete component;
		component = NULL;
	}
}

可以看出,component的“结束生命”的控制权在析构函数里,
new/delete必须遵守在同一个层次里面。所以肯定new也必须在构造函数里面。
可惜构造是在外部手动构造的。像这种多次引用的,建议使用引用计数。

Person *person = new Person("淼淼");
DecorateA *deA = new DecorateA();
DecorateB *deB = new DecorateB();
DecorateC *deC = new DecorateC();
 
deA->setComponent(person);
deB->setComponent(deA);
deC->setComponent(deB);
deC->show();
deA->Release();
deB->Release();
deC->Release();
person->Relase();

B的: 其他的也相似

DecorateB::clear() {
  	if(component != nullptr) {
		component->Relase();
		component = nullptr;
	}
}
DecorateB::~DecorateB() {
	this->clear();
}
void DecorateB::setComponent(Person* component) {
        this->clear();
	this->component = component;
        if(component) component->AddRef();
}

对了,C++没有参数不用写void,那是C的标准。这里参考的是COM的接口AddRef/Release

解决方案:3分
对电脑而言没有乱码,只有二进制字节;对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A
推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。
解决方案:2分
其实还有一个办法
从代码看
Person

DecorateA
两个类没有任何直接关系
DecorateA 只是把 Person 作为 成员使用
因此 DecorateA 的析构函数,完全可以不必关心 Person 指针。
让 负责 new Person 的代码 ,析构 Person 就可以了
这样即便不是 new 的对象 DecorateA等类 依然可以引用

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明设计模式–装饰模式 的析构问题