Зависимость объекта и обработка ситуаций, когда одна из них больше не существует - PullRequest
2 голосов
/ 03 января 2012

Есть этот код:

#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 не будет помещен в свободное хранилище (например, в стек). Существуют ли какие-либо шаблоны проектирования, позволяющие отслеживать, существует ли еще используемый объект и имеет ли смысл вызывать его функции?

Ответы [ 2 ]

2 голосов
/ 03 января 2012

Вы все еще можете использовать 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 на лямбду, [](void*){}.

1 голос
/ 03 января 2012

Одно решение будет для CC иметь статическую продолжительность хранения:

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

Таким образом, CC создается только один раз, когда returnNCC() вызывается впервые и остается активным до тех пор, пока работает программа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...