2014-08-29 5 views
5

Является ли законным разрушать и создавать объект базового класса для восстановления части состояния, известного базовому классу?Является ли законным явное вызов деструктора/конструктора класса?

class C : public BaseClass {...}; 

C c; 
c.BaseClass::~BaseClass(); 
new (static_cast<BaseClass*>(&c)) BaseClass; 

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

+0

№ Для начала нет гарантии, что '& c' совпадает с адресом своего подобъекта базового класса. –

+0

Справедливая точка. Я добавил актерский состав. –

+0

Метод 'restore 'в базовом классе не будет? Это звучит как проблема X-Y. – sp2danny

ответ

8

Нет, это не законно. Вы не можете заменить базовый подобъект объекта.

C++ 11 3.8/7 указывает, что вы можете только повторно использовать для хранения объекта, если

исходный объект был наиболее производный объект (1.8) типа Т и новый объект является наиболее производный объект типа T (то есть они не являются подобъектами базового класса).

Объект, который вы заменили, был подобъектом базового класса, а не самым производным объектом, и поэтому запрещен.

Если вы должны были заменить весь объект (т. Е. Позвонить ~C, а затем построить новый C), тогда это будет законным, но опасным. Если конструктор бросил, то объект будет уничтожен второй раз в конце его срока службы. Это даст неопределенное поведение.

+0

Можете ли вы объяснить, что останавливает объект типа C? Я не пытаюсь заменить или изменить объект, просто повторно инициализирую его область базового класса. –

+0

@ JamesT.Huggett: 'new (...) BaseClass' создает объект типа' BaseClass', а не 'C'. –

+0

@MikeSeymour Однако был вызван только деструктор базового класса. Я понимаю, что OP пытается «повторно инициализировать» подобъект базового класса, не уничтожая повторную инициализацию всего самого производного объекта. – Angew

2

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

+0

Идея состоит в том, чтобы сбросить состояние базового объекта, не касаясь полей, добавленных в производный класс. Я не уверен, что вы подразумеваете под «быть C». –

+0

Почему виртуальные деструкторы актуальны? Я явно называю деструктор, которого я хочу. –

+1

«be C» относится к вашему классу C. То, что вы здесь делаете, совершенно неверно и не будет работать. Если dtor 'BaseClass' является виртуальным, будет вызываться деструктор' C', и объект будет полностью уничтожен, хотя память не будет освобождена, потому что вы не назовете 'delete'. Если это не виртуально, возможно, вы уничтожите бит 'BaseClass' только, но я сомневаюсь, что это гарантированно сработает. Вместо этого просто создайте простой 'reset()' метод на вашем 'BaseClass'. –

Смежные вопросы