У меня есть объект, который я хочу "преобразовать" в другой объект. Для этого я использую placement new
на первом объекте, который создает новый объект другого типа поверх его собственного адреса.
Рассмотрим следующий код:
#include <string>
#include <iostream>
class Animal {
public:
virtual void voice() = 0;
virtual void transform(void *animal) = 0;
virtual ~Animal() = default;;
};
class Cat : public Animal {
public:
std::string name = "CAT";
void voice() override {
std::cout << "MEOW I am a " << name << std::endl;
}
void transform(void *animal) override {
}
};
class Dog : public Animal {
public:
std::string name = "DOG";
void voice() override {
std::cout << "WOOF I am a " << name << std::endl;
}
void transform(void *animal) override {
new(animal) Cat();
}
};
Вы можете видеть, что когда Dog
вызывается с помощью transform
он создает нового Cat
поверх данного адреса.
Далее я вызову Dog::transform
со своим собственным адресом:
#include <iostream>
#include "Animals.h"
int main() {
Cat cat{};
Dog dog{};
std::cout << "Cat says: ";
cat.voice() ;
std::cout << "Dog says: ";
dog.voice();
dog.transform(&dog);
std::cout << "Dog says: ";
dog.voice();
std::cout << "Dog address says: ";
(&dog)->voice();
return 0;
}
Результаты этого:
Cat says: MEOW I am a CAT
Dog says: WOOF I am a DOG
Dog says: WOOF I am a CAT
Dog address says: MEOW I am a CAT
Мои вопросы:
- Эта операция считается безопасной или она оставляет объект в нестабильном состоянии?
- После преобразования я вызываю
dog.voice()
. Он правильно печатает имяCAT
(теперь это кот), но все равно пишетWOOF я am a
, хотя я и подумал, что он должен вызыватьvoice
методCat
? (Вы можете видеть, что я вызываю тот же метод, но по адресу ((&dog)->voice()
) все работает правильно.