例から始めましょう:
#include <cstdio>
struct Base { virtual ~Base() {} virtual void foo() = 0; };
struct P: Base { virtual void foo() override { std::printf("Hello, World!"); } };
struct N: Base { virtual void foo() override {} };
void magic(Base& b);
// Example implementation that changes the dynamic type
// {
// void* s = dynamic_cast<void*>(&b);
// b.~B();
// new (s) N();
// }
int main() {
std::aligned_storage<sizeof(P), alignof(P)> storage;
void* s = static_cast<void*>(storage);
new (s) P();
Base& b = *static_cast<Base*>(s);
magic(b);
b.foo();
}
標準によると、何をb.foo()
印刷する必要がありますか?
個人的な意見: でb
インスタンスを破棄した後に古くなったため、未定義magic
です。この場合、 で置き換えるb.foo()
とstatic_cast<B*>(s)->foo()
合法になりますか?
合法である (または合法ではない) 例が得られたので、私たち標準主義者全員が直面しているより一般的な問題は、オブジェクトの動的な型を変更することが許可されているかどうかです。C++ コンパイラが (幸いなことに) ストレージを再利用する可能性があることは既にわかっているため、少し注意が必要です。
質問は理論的なように思えるかもしれませんが、コンパイラーに直接適用できます。コンパイラーはb.foo()
上記b.P::foo()
のプログラムで非仮想化できますか?
したがって、私は探しています:
- 私自身の小さなプログラムに関する明確な答え (私は思いつきませんでした)。
- オブジェクトの動的な型を変更する合法的な方法の可能な例 (単一で十分です)。