对象依赖关系和处理其中一个不再存在的情况



有这样的代码:

#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的对象即将不存在时,调用它的函数可能会引起麻烦。

一个解决方案是保留在NotCleverClass的弱指针(boost::weak_ptr)与引用检查器的CleverClass对象,但仍然有一个问题,当CleverClass的对象不打算放在自由存储(例如在堆栈)。是否存在一些设计模式来监视使用对象是否仍然存在以及调用其函数是否有意义?

即使对象具有自动存储时间,您仍然可以使用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中,您可以将null_delete函子替换为lambda [](void*){}

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

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

这样,CC只在第一次调用returnNCC()时被构造一次,并且在程序运行期间保持存活。

最新更新