我可以破坏并反对,然后使用相同的名称再次使其平化

问题描述 投票:-2回答:2

我正在为其他人编写的代码创建单元测试,无法对其进行修改。

我试图销毁一个对象,然后从头开始实例化它(因此构造函数将其置于初始状态)

这是我的代码:

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()移动到某些状态,但不能移动到其他状态。

[我在互联网上看过有关析构函数的信息,并且我读到即使不是很好的做法,也可以显式调用它们。

也许有人可以告诉我为什么当我破坏然后再次实例化对象时,编译器会失败吗?

PD:析构函数是默认的析构函数

state::State_Machine::~State_Machine() {}
c++ destructor
2个回答
0
投票

不能在调用析构函数后不久在同一个作用域级别上声明另一个具有相同名称的变量。析构函数从作用域中删除旧名称。

为了解决您的问题,我建议您仅添加新级别的作用域,因为在任何给定时间似乎您仅在几行中使用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()); }

如果仍然要显式调用析构函数,则必须确保在同一对象上多次调用析构函数是安全的(您说无法修改现有代码,因此这将奏效,否则将不会。” t)。在实践中,如果这种方法行之有效,我会感到惊讶,因为大多数析构函数都假定该对象将被销毁,并且不会花时间将其标记为已销毁(这可能需要额外的状态,并且肯定会需要一定的周期) 。

[如果您仍然决心,尽管存在复杂性和风险,您可以编写如下内容:

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

new (&state_machine_test_off) state::State_Machine;

这会利用位置new,如果您正确使用范围,则完全没有必要(见上文)。您还必须考虑如果构造函数失败,会发生什么情况,特别是因为您将still需要处理已销毁的对象并再次调用其析构函数。


1
投票

问题是您正在重新定义一个已经定义的变量。当你做

state::State_Machine state_machine_test_off; 

您基本上将范围内的名称state_machine_test_off锁定为该变量。您以后不能执行state::State_Machine state_machine_test_off;来重置它,因为它试图定义一个新变量并且名称state_machine_test_off已经被使用。

要在销毁对象后重建对象,您需要使用placement new使它再次在该对象上调用构造函数。看起来像

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

现在在state::State_Machine的存储中有一个新的默认构造的state_machine_test_off


这就是说,如果您只是将对象重新分配为默认的构造值,那么所有这些手动调用和未定义行为的可能性就会消失,>

state_machine_test_off = state::State_Machine{};
© www.soinside.com 2019 - 2024. All rights reserved.