2013-03-18 3 views
1

Предположим, что у нас есть три класса: A, B, C. Оба A и B владеют указателем на класс C. Не должно быть так, что два экземпляра класса A имеют один и тот же указатель на объект C , но в то же время объект C свободен для указания экземпляром класса B.уникальный указатель внутри класса

Есть ли способ реализовать это в C++ (11)?

====== ====== EDIT

Итак, давайте более подробно. Когда я создаю объекты C, я добавляю их указатели в контейнер в объекте B. Объекты A могут иметь или не указатель на C. Важно то, что не более одного A указывает на тот же C, который может на самом деле произойти из-за ошибки пользователя. Как только A указывает на C априори, он должен продолжать указывать, что C для всей его жизни.

Я бы пошел за уникальными указателями, но мне нужны копии их в контейнер B!

+0

Есть много разных способов. Меняются ли указатели? Они назначаются при строительстве? Создается ли 'C' каждый раз, когда создается' A'? Что должно произойти, когда код пытается назначить один и тот же указатель на два 'A'? –

+0

Да, но это не тривиально. – metal

+0

'B' может просто использовать обычный указатель. Этот дизайн сомнительный, хотя он не похож на уникальную собственность. – Pubby

ответ

1

Это звучит, как вы хотите исключение быть выброшен, если тот же указатель присваивается более одного экземпляра A.

Это решение может отслеживать используемые указатели для предотвращения переназначения. Это не потокобезопасный ... вам нужно будет изменить это, чтобы добавить синхронизацию, если вам это нужно.

class A 
{ 
    // The pointers used by all instances of A 
    static std::set<C*> used_ptrs; 

    // The pointer used by this instance of A 
    C* the_c; 

    // Sets the pointer if it is valid 
    void set_c(C* c) 
    { 
    if (the_c) 
     throw std::runtime_error("C pointer is already set in this A"); 

    if (used_ptrs.count(c)) 
     throw std::runtime_error("C pointer is already set in another A"); 

    the_c = c; 
    used_ptrs.insert(c); 
    } 

    // The pointer is presumed to be unassigned at construction 
    A() : the_c(NULL) {} 

    // The pointer is removed from the set at destruction 
    ~A() 
    { 
    if(the_c); 
     used_ptrs.erase(the_c); 
    } 

    // Copying A is invalid by your description 
    A(const A&) = delete; 
    A& operator= (const A&) = delete; 
} 
+0

Приятный и чистый, поздравляю! – DarioP

0

Я думаю, вам нужно сделать немного бухгалтерии внутри вашего класса, возможно, используя статический член unordered_map. Я проверил приведенный ниже код для работы:

using namespace std; 

struct C; 

struct A 
{ 
    void SetPointerToC(C & aC) 
    { 
    if (mAllC.find(&aC) != mAllC.end()) 
     assert(false); // multiple instances of A should not point to the same C 

    mAllC[&aC] = this; 
    mC = &aC; 
    } 

    ~A() 
    { 
    mAllC.erase(mC); 
    } 

private: 

    // A is not copyable as to prevent multiple A instances having 
    // mC with the same value 
    A(const A &); 
    A & operator=(const A &); 

    static unordered_map<C*, A*> mAllC; 
    C * mC; 
}; 

unordered_map<C*, A*> A::mAllC; 

struct C 
{ 

}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    A a;  
    A a2; 
    C c; 
    a.SetPointerToC(c); // works 
    a2.SetPointerToC(c); // assert! 

    return 0; 
} 
Смежные вопросы