2015-10-27 2 views
3

Скажем, у нас есть класс Foo:дизайн головной боли с unique_ptr

class Foo { 
public: 
    ... 
}; 

Foo имеет метод экземпляра, который либо преобразует экземпляр Foo в другой Foo например, или возвращает тот же Foo экземпляр:

<some appropriate pointer type to Foo> Foo::tryToTransform() { 
    if (canBeTransformed()) { 
    <delete this Foo instance>; 
    return <new instance of Foo>; 
    } 
    else { 
    return <this instance of Foo>; 
    } 
} 

Код клиента:

<some appropriate pointer type to Foo> foo = ...; 
... 
foo = foo->tryToTransform(); 

Это легко сделать с голыми указателями:

Foo* Foo::tryToTransform() { 
    if (canBeTransformed()) { 
    delete this; 
    return new Foo(...); 
    } 
    else { 
    return this; 
    } 
} 

Foo* foo = ...; 
... 
foo = foo->tryToTransform(); 

Но что, если клиентский код использует unique_ptr вместо голого указателя? То есть, в идеале я хотел бы, чтобы клиентский код, чтобы выглядеть следующим образом:

unique_ptr<Foo> foo = ...; 
... 
foo = foo->tryToTransform(); 

Как следует Foo::tryToTransform() быть определены для того, чтобы дать возможность такой (или подобный) код клиента?

+3

Aiee! 'delete this' - это ужасная ** идея. Сделайте свой метод преобразования статическим методом, и все ваши беды исчезнут. – nneonneo

+1

Кроме того, я вижу, что это применимо только в том случае, если вы хотите * изменить * объект * тип *, т. Е. Преобразовать экземпляр 'X' в экземпляр' Y'. В противном случае, почему вы удаляете и воссоздаете объект? –

+0

@nneonneo 1. Я не поклонник 'delete this', но в некоторых случаях это нормально, см., Например, [эту статью часто задаваемых вопросов] (https://isocpp.org/wiki/faq/freestore-mgmt# delete-this) 2. Как бы заставить 'Foo :: tryToTransform()' static помогать проблеме unique_ptr' каким-либо образом? – user1387866

ответ

6

Поскольку ваша функция tryToTransform является функцией члена , вызывающий абонент сохраняет право собственности на unique_ptr. Поэтому невозможно (без грязных трюков), чтобы удалить вызывающего абонента изнутри функции-члена.

Таким образом, вы потребность статическая функция, которая принимает право собственности на unique_ptr:

class Foo { 
    static unique_ptr<Foo> tryToTransform(unique_ptr<Foo> ptr) { 
     if(...) { 
      return unique_ptr<Foo>(new Foo()); // old ptr is destroyed 
     } else { 
      return ptr; 
    } 
}; 

Позвоните в

unique_ptr<Foo> foo = ...; 
... 
foo = Foo::tryToTransform(move(foo)); 

Это работает, имея tryToTransform взять на себя ответственность за unique_ptr. Затем он может уничтожить указатель по своему усмотрению.

Смежные вопросы