当其中一个不再存在时,对象依赖和处理情况

时间:2012-01-03 18:57:24

标签: c++ design-patterns

有这段代码:

#include <iostream>

class CleverClass{
public:
    CleverClass() : number(55){}
    void cleverOperation(){
        std::cout << number << std::endl;
    }
private:
    int number;
};

class NotCleverClass{
public:
    NotCleverClass(CleverClass* cc) : cleverClass(cc){}
    void callCleverOperation(){
            // throw exception when cleverClass object doesn't exist anymore
        cleverClass->cleverOperation();
    }
private:
    CleverClass* cleverClass;
};

NotCleverClass returnNCC(){
    CleverClass CC;
    NotCleverClass NCC(&CC);
    NCC.callCleverOperation(); // prints 55
    return NCC;
}

int main()
{
    NotCleverClass returnedNCC = returnNCC();
    returnedNCC.callCleverOperation(); // prints -858993460
    return 0;
}

类NotCleverClass的对象依赖于类CleverClass的对象。当类CleverClass的对象存在时,类NotCleverClass的对象可以使用它的函数cleverOperation(),并且一切正常。但是,当CleverClass类的对象将失去存在时,调用它的函数可能会引起麻烦。

其中一个解决方案是使用引用检查器保留CleverClass对象的NotCleverClass弱指针(boost :: weak_ptr),但是当cleverClass的对象不会被放置在免费存储上时仍然存在问题(例如,堆)。是否有一些设计模式来监视所使用的对象是否仍然存在以及调用其功能是否有任何意义?

2 个答案:

答案 0 :(得分:2)

即使对象具有自动存储持续时间,您仍然可以使用weak_ptr;你可以给shared_ptr一个什么都不做的自定义删除器;并确保它在对象本身之前被销毁,方法是将它放在与对象相同的范围内。像这样:

class NotCleverClass{
public:
    NotCleverClass(weak_ptr<CleverClass> cc) : cleverClass(cc){}
    void callCleverOperation(){
        // throw bad_weak_ptr when cleverClass object doesn't exist anymore
        shared_ptr<CleverClass>(cleverClass)->cleverOperation();
    }
private:
    weak_ptr<CleverClass> cleverClass;
};

struct null_delete { void operator()(void*) const {} };

NotCleverClass returnNCC(){
    CleverClass CC;
    shared_ptr<CleverClass> shared_cc(&CC, null_delete());

    NotCleverClass NCC(shared_cc);
    NCC.callCleverOperation(); // prints 55
    return NCC;

    // shared_cc destroyed here: NCC::cleverClass is safely invalidated
    // CC destroyed here: no dangling references remain
}

这应该适用于Boost或C ++ 11智能指针。在C ++ 11中,您可以使用lambda null_delete替换[](void*){}仿函数。

答案 1 :(得分:1)

一个解决方案是CC具有静态存储持续时间:

NotCleverClass returnNCC(){
    static CleverClass CC;   // Note the keyword static there
    NotCleverClass NCC(&CC);
    NCC.callCleverOperation(); // prints 55
    return NCC;
}

这种方式CC只在第一次调用returnNCC()时构造一次,并且只要程序运行就会保持活动状态。