Как реализовать ссылочный конструктор? - PullRequest
5 голосов
/ 10 марта 2011

Я ищу способ сделать так, чтобы мой конструктор сделал ссылку на другой объект следующим образом:

Foo object1("File1");
Foo object2("File1");

Первый объект создается нормально.Второй объект видит, что уже существует объект, использующий параметр «File1», и сам ссылается на первый объект.Я знаю, что это не может быть напрямую возможно сделать таким образом.Я сохраняю статический вектор Foo * для отслеживания выделенных объектов.

Я знаю, что могу сделать все члены указателей класса и для первого случая создать (New) их.Во втором случае я бы не стал создавать их и указывать на первый объект.Кроме того, второй объект гарантированно имеет более короткий срок службы, чем первый.

Итак, есть ли простой / элегантный способ сделать это?

РЕДАКТИРОВАТЬ: Спасибодля всех отличных решений.Мне нравятся все они, но я могу использовать только один.Я сохраню все эти знания для дальнейшего использования.

Я выбираю решение static map <string, FooObject*>.Сначала я подумал, что это глупо, но после дальнейшего рассмотрения он показался мне элегантным.

Единственное добавление, которое я вижу сейчас, - это добавление счетчика ссылок в FooObject.Таким образом, в конструкторе Foo я могу увеличить счетчик ссылок.В деструкторе уменьшите счетчик.Если счетчик равен нулю, удалите его с карты.Таким образом, нет утечек памяти, и объекты могут быть уничтожены в любом порядке.Я предполагаю, что эта методология - shared_ptr esque.За это идет @Travis.

Спасибо, Джеймс.

Ответы [ 4 ]

6 голосов
/ 10 марта 2011

Попробуйте использовать static map<string, object*> в качестве переменной, где object - это остаток класса, который вам нужен.

1 голос
/ 10 марта 2011

Вы можете использовать менеджер ресурсов.Он должен иметь такой интерфейс:

class ResourceManager
{
public:
   Foo* GetFoo(some id type, maybe file name);
   void ReleaseFoo(Foo* fooObj);
}

Внутри он будет искать, есть ли объект Foo *, который использует тот же идентификатор, что и новый идентификатор, и если он выходит, он возвращает старый объект Foo *, иначе он создастновый объект типа Foo *.Он также будет подсчитывать количество объектов Foo * для каждого идентификатора.Когда вызывается функция Release, она уменьшает число для этого идентификатора (который идентифицирует уникальный объект), а если оно равно 0, оно удаляет объект.

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

0 голосов
/ 10 марта 2011

Вам просто нужен фабричный метод, который возвращает Foos и всегда вызывает его, ожидая ссылку. Затем вы сохраняете их в статической карте и проверяете их, когда вас спрашивают.

Foo &file = getmefile("file1");
Foo &file2 = getmefile("file1");

Foo &getmefile(string filename){
   if (foos.find(filename) == foos.end() ) {
        foos[filename] = Foo(filename);
   }
   return foos[filename];
}
0 голосов
/ 10 марта 2011

Возможно, это звучит как мухи http://en.wikipedia.org/wiki/Flyweight_pattern

Если вы находитесь в однопоточном окружении, вы можете просто иметь статический std::map<std::string, ObjectImpl*> в своем классе и использовать его в конструкторе.Вы должны использовать шаблон pimpl для хранения фактической реализации, а при создании объекта проверить, доступна ли реализация.Если это так, просто установите указатель немедленно.Если вам нужно очистить, когда не осталось ссылок, вы можете добавить дополнительный код, чтобы справиться с этим.

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