Могу ли я уничтожить и возразить, а затем возбудить его снова с тем же именем - PullRequest
0 голосов
/ 30 апреля 2020

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

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

Это мой код:

state::State_Machine state_machine_test_off; 

//Check that OFF is initial state

EXPECT_EQ(States::OFF,state_machine_test_off.get_state());

//Change and check the behaviour from OFF to the other States

state_machine_test_off.change_state(States::LOADED);
EXPECT_EQ(States::LOADED,state_machine_test_off.get_state());
state_machine_test_off.~State_Machine(); //Destructor to iniciate again the process

state::State_Machine state_machine_test_off;
state_machine_test_off.change_state(States::INITIALISED);
EXPECT_NE(States::INITIALISED,state_machine_test_off.get_state());
state_machine_test_off.~State_Machine(); //Destructor to iniciate again the process

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

Я посмотрел в inte rnet о деструкторах, и я читал, что их можно вызывать явно, даже если это не очень хорошая практика.

Может быть, кто-нибудь подскажет мне, почему этот компилятор не работает, когда я уничтожаю и затем снова создать экземпляр объекта?

PD: деструктор является деструктором по умолчанию

state::State_Machine::~State_Machine() {}

Ответы [ 2 ]

1 голос
/ 30 апреля 2020

Проблема в том, что вы переопределяете переменную, которую вы уже определили. Когда вы делаете

state::State_Machine state_machine_test_off; 

, вы в основном блокируете имя state_machine_test_off в области видимости этой переменной. Позже вы не сможете выполнить state::State_Machine state_machine_test_off; для его сброса, потому что он пытается определить новую переменную, а имя state_machine_test_off уже занято.

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

new (&state_machine_test_off) state::State_Machine();

А теперь в хранилище state_machine_test_off появился новый стандарт по умолчанию state::State_Machine.


При этом все эти ручные вызовы и шансы неопределенного поведения исчезнут go, если вы просто переназначите объект на значение по умолчанию, например

state_machine_test_off = state::State_Machine{};
0 голосов
/ 30 апреля 2020

Вы не можете просто объявить другую переменную с тем же именем на том же уровне области видимости, даже после вызова деструктора. Деструктор не не удаляет старое имя из области.

Чтобы решить вашу проблему, я бы предложил просто добавить новые уровни области, поскольку кажется, что вы используете только state::State_Machine на несколько строк в любой момент времени.

{ state::State_Machine state_machine_test_off;
  state_machine_test_off.change_state(States::LOADED);
  EXPECT_EQ(States::LOADED,state_machine_test_off.get_state()); }

{  state::State_Machine state_machine_test_off;
   state_machine_test_off.change_state(States::INITIALISED);
   EXPECT_NE(States::INITIALISED,state_machine_test_off.get_state()); }

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

Если вы по-прежнему настроены, несмотря на сложность и риски, вы можете написать что-то вроде этого:

state_machine_test_off.~State_Machine(); //Destructor to iniciate again the process

new (&state_machine_test_off) state::State_Machine;

Это использует размещение new, что совершенно не нужно, если вы просто используете сфера правильно (см. выше). Вы также должны рассмотреть, что произойдет, если конструктор потерпит неудачу, тем более что вам все еще потребуется обработать уже удаленный объект с повторным вызовом его деструктора.

...