Ответ таков: вам все равно не нужно знать, поскольку ваш дизайн нарушен.
Во-первых, Destroy
звучит как плохая идея, более того, если он вызывается в объекте, который не являетсяответственность за уничтожение другого объекта.Код из метода Destroy
принадлежит деструктору ApplicationService
(который, будем надеяться, виртуален, хотя в этом случае он фактически не нужен), который в отличие от C # вызывается в совершенно определенный момент времени.
Как только вы это сделаете, вы (надеюсь) поймете, что MyClass
не несет ответственности за уничтожение appService_
, поскольку оно не владеет им.За это отвечает ConsumerClass
(точнее, метод DoSomething
), который действительно управляет реальной службой и фактически уничтожает ее автоматически, как только вы переместили код Destroy
в деструктор.Разве не приятно, что RAII делает все чисто и автоматически?
class MyClass
{
public:
MyClass(ApplicationService& app): appService_(app)
{
}
private:
ApplicationService& appService_;
}
class ConsumerClass
{
DoSomething()
{
CustomApplicationService customAppService;
MyClass myclass(customAppService);
myclass...
}
}
class ApplicationService
{
public:
virtual ~ApplicationService()
{
//code from former Destroy method
}
}
class CustomApplicationService
{
public:
virtual ~CustomApplicationService()
{
//code from former Destroy method
}
}
ИМХО это идеальный чистый C ++ способ обойти это, и проблема определенно не является причиной для спама shared_ptr
s.Даже если вам действительно нужен выделенный метод Destroy
и вы не можете переместить код в деструктор (который я бы выбрал в качестве мотивации для переосмысления проекта), вы все равно будете вызывать Destroy
из DoSomething
, как снова, MyClass не несет ответственности за уничтожение appService_ .
EDIT: Согласно вашему обновлению (и моему глупому игнорированию аргумента something
), ваш дизайн действительно выглядит вполне корректным(по крайней мере, если вы не можете возиться с изменением ApplicationService
), извините.
Несмотря на то, что члены класса должны быть уничтожены в обратном порядке построения, я не уверен, что это также относится к локальным автоматическим переменным.Чтобы удостовериться, что деструкторы вызываются в определенном порядке, вы можете ввести вложенные области видимости, используя простые блоки:
void DoSomething()
{
CustomApplicationService customAppService;
{
MyClass myclass(customAppService);
myclass...
} // myclass destroyed
} // customAppService destroyed
Конечно, по-прежнему совершенно нет необходимости использовать динамическое распределение, не говоря уже о shared_ptr
s.Хотя вложенные блоки немного разрушают код, это ничто не против уродства динамического выделения, примененного не динамическим образом и без причины, и, по крайней мере, «хорошо выглядит семантическим способом» с объявлением customAppService
сверхублока;)