Я использую отличный фреймворк Poco для ведения журнала. В настоящее время я определяю Logger и LogStream следующим образом в своих заголовочных файлах:
#Foo.h
....
class Foo
{
private:
Poco::Logger &logger = Poco::Logger::get("Foo");
Poco::LogStream logStream{ logger };
};
Это служило очень хорошо, пока я не начал использовать буст :: ди. Когда я использую Boost Injector, чтобы создать такой объект для Foo,
injector.create<Foo>();
Я получаю сообщение об ошибке компилятора,
attempting to reference a deleted function
Однако, если я удалю определение LogStream, я не получу ошибку компилятора. Можно ли объявить LogStream в заголовке, не определяя его? Я новичок в С++, и я был бы рад, если бы кто-нибудь мог указать, что я здесь делаю неправильно и как это сделать правильно. Спасибо большое.
Спасибо @rafix07, что нашли время написать это. Я попробую ваше предложение.
Вам не нужно хранить Poco::Logger &logger как член данных этого класса (ссылки не могут быть скопированы, поэтому оператор присваивания копирования по умолчанию не может быть сгенерирован). Вы могли бы сделать Poco::SharedPtr<Poco::LogStream> logStream{new Poco::LogStream(Poco::Logger::get("Foo"))};. Вызовите Logger::get и передайте возвращаемое значение в ctor Poco::LogStream.
Привет @ rafix07, память не будет управляться автоматически при использовании «нового», не так ли? Нужно ли нам использовать «удалить» в dtor?
Привет, SharedPtr контролирует время жизни LogStream, вы не делаете это вручную.
Привет @ rafix07, большое спасибо за ваши предложения. Я попробовал, и это сработало. Можете ли вы опубликовать это как ответ?





Экземпляры Foo не могут быть скопированы по двум причинам:
1) logger является ссылкой, ссылка должна быть инициализирована при создании Foo, поэтому единственный способ
для этого нужно использовать конструкторы.
Компилятор не может сгенерировать операцию копирования присваивания. Так что Foo f1,f2; f1 = f2; не может работать.
2) Базовым классом LogStream является std::ostream, в котором отключены операции копирования.
Решение:
убрать logger как элемент данных, здесь он лишний,
потому что мы можем вызвать Poco::Logger, пока LogStream инициализирован.
class Foo {
//...
Poco::SharedPtr<Poco::LogStream> logStream{
new Poco::LogStream(Poco::Logger::get("Foo"))};
};
Чтобы сделать Foo копируемым, вы можете использовать Poco::SharedPtr.
Будет ли какое-либо влияние, если вместо этого будет использоваться std:shared_ptr?
Вы можете легко использовать std::shared_ptr здесь. Нет никакой разницы.
Большое спасибо @rafix07. Прекрасно работает.
Вероятно, ваши экземпляры
Fooкопируются, но базовым классомPoco::LogStreamявляетсяstd::ostream, который не может быть скопирован, поэтому ваши экземплярыFooне могут быть скопированы. Чтобы избежать этой проблемы, вы можете сделатьlogStreamсвоего рода умным указателем,std::shared_ptrилиPoco::SharedPtr.