我有一个对象,我想把它‘转换’成另一个对象。为此,我在第一个对象上使用了一个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();
}
};
您可以看到,当使用transform
调用Dog
时,它会在给定地址之上创建一个新的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 I am a
,即使我认为它应该调用Cat
的voice
方法?(您可以看到,我调用了相同的方法,但通过地址((&dog)->voice()
),一切都正常工作。发布于 2019-04-16 23:13:32
1)不能,这是不安全的,原因如下:
2)我在MSVC2015上观察到,dog.voice()
将在不检查实际虚拟表的情况下调用Dog::voice
。在第二种情况下,它检查已修改为Cat::voice
的虚拟表。但是,正如其他用户所经历的那样,其他一些编译器可能会执行一些优化,并在所有情况下直接调用与声明匹配的方法。
发布于 2019-04-16 23:15:23
这段代码至少有三个问题:
当placement
Dog
对象。https://stackoverflow.com/questions/55711220
复制相似问题