Я понимаю, почему shared_from_this не работает в конструкторе. Я нашел несколько сообщений здесь clearly, объясняя почему. Я также видел для него workaround. Моя проблема связана с этим, но я ищу элегантное обходное решение.Проблемы с shared_from_this в конструкторе для цепочки вызовов
Я очень нравится этот вид дизайна
class Foo : public enable_shared_from_this<Foo> {
public:
typedef shared_ptr<Foo> Ptr;
Ptr setA(int) {/* .... */ return this->shared_from_this(); }
Ptr setB(int) {/* .... */ return this->shared_from_this(); }
Ptr setC(int) {/* .... */ return this->shared_from_this(); }
};
так что я могу Шлейфовое так, что я нахожу очень читаемый
Foo::Ptr foo = make_shared<Foo>();
foo->setA(3)->setB(4)->setC(5);
Однако мои методы Setx делать больше, чем просто присвоить значение к собственности, они могут делать несколько более сложные вещи (например, устанавливать другие свойства и т. д.). Поэтому я хотел бы использовать их в своем конструкторе. т.е.
Foo::Foo(int a, int b, int c) {
setA(a);
setB(b);
setC(c);
}
Конечно, это сбой. Однако в моем случае мне не нужен общий этот указатель в моем конструкторе. Это всего лишь побочный эффект моего желания в конце концов.
Загрязненное исправление может быть я просто создаю кучу частных методов setX_, которые выполняют фактическое назначение и другие задачи, но ничего не возвращают. Конструктор вызывает их. Затем у меня есть общедоступные методы setX, просто вызывающие частные, а затем возвращают -> shared_from_this(). Это безопасно, но немного PITA. Можно ли проверить, существует ли общий указатель на без сбоев? т.е.
class Foo : public enable_shared_from_this<Foo> {
public:
typedef shared_ptr<Foo> Ptr;
Ptr setA(int) { /*.....*/ return getThis(); }
protected:
Ptr getThis() {
return safe_to_get_this ? this->shared_from_this : Ptr();
}
};
UPDATE
я должен был бы сделать это ясно в моей должности, извинения за не делать этого. Причина, по которой я использую интеллектуальные указатели, - это не так, я могу сделать цепочку. Обычно я использую ссылки для этого, если позволяет ситуация.
Но в этом случае Foo (и другие классы) относятся к структуре, подобной графу, они имеют зависимости друг от друга, множественные отношения между родителями и дочерними элементами и т. Д. Поэтому я использую сочетание между общими и слабыми указателями. Но мне нужны методы для возврата shared_ptrs, поэтому я могу использовать слабый или проверять на нуль, если это необходимо (они создаются с использованием фабричных методов, и есть методы find/get, которые нуждаются в проверке на null). В основном это физическая система с различными типами частиц и ограничениями между частицами. Я изначально написал это с моей собственной реализацией умных указателей много лет назад, и теперь я обновляю его до C++ 11. Я мог бы заставить методы setX возвращать ссылки и иметь один метод getThis(), который возвращает общий указатель (это то, что я делал раньше), но потом я беспокоюсь, что он немного несовместим с некоторыми методами, возвращающими интеллектуальные указатели, возвращающие другие Рекомендации.
Foo::Ptr foo = World::create();
foo->setA().setB().setC();
foo = World::find(...);
if(foo) foo->setA().setB();
Я просто предпочитаю согласованность всегда возвращающих указателей, в отличие от иногда указателей и иногда ссылок. Если для этого нет строгого руководства, которое можно кратко изложить.
UPDATE2
Это (не очень элегантно) обходной путь я использую в настоящее время.Мне просто интересно, есть ли способ сделать это без ручного отслеживания _isInited;
class Foo : public enable_shared_from_this<Foo> {
public:
typedef shared_ptr<Foo> Ptr;
Foo() {
_isInited = false;
setA();
setB();
setC();
_isInited = true;
}
Ptr setA(int) {/* .... */ return getThis(); }
Ptr setB(int) {/* .... */ return getThis(); }
Ptr setC(int) {/* .... */ return getThis(); }
protected:
bool _isInited;
Ptr() {
return _isInited ? this->shared_from_this() : Ptr();
}
};
Если вы просто хотите объединить вызовы функций членов, зачем использовать указатели для начала? Просто верните ссылку на сам класс, и вам не нужно беспокоиться о 'shared_from_this' и т. Д. И я рекомендую вам взглянуть на интеллектуальные указатели с точки зрения * ресурса * вместо простых указателей, которые автоматически удаляются. –