Skip to main content
The 2026 Annual Developer Survey is live— take the Survey today!
added 228 characters in body
Source Link
ecatmur

The reinterpret_cast is unsafe; you should always use dynamic_cast. It is irrelevant that I1 and I2 are pure virtual classes; as subobjects of C12 they have nonzero storage requirements. Indeed, in the following program:

int main() {
    I2 * p2 = new C12; 
    I1 * p1 = reinterpret_cast<I1*>(p2);
    std::cout << p2 << '\n';
    std::cout << p1 << '\n';
    std::cout << dynamic_cast<I1*>(p2) << '\n';
    p1->nb1();
}

the output is:

0x14de0c8
0x14de0c8
0x14de0c0   // !!!
nb2         // !!!

You may be thinking of the empty base optimization (1.8p5); but this does not apply to classes with virtual methods, which require a vptr.

The reinterpret_cast is unsafe; you should always use dynamic_cast. It is irrelevant that I1 and I2 are pure virtual classes; as subobjects of C12 they have nonzero storage requirements. Indeed, in the following program:

int main() {
    I2 * p2 = new C12; 
    I1 * p1 = reinterpret_cast<I1*>(p2);
    std::cout << p2 << '\n';
    std::cout << p1 << '\n';
    std::cout << dynamic_cast<I1*>(p2) << '\n';
    p1->nb1();
}

the output is:

0x14de0c8
0x14de0c8
0x14de0c0   // !!!
nb2         // !!!

The reinterpret_cast is unsafe; you should always use dynamic_cast. It is irrelevant that I1 and I2 are pure virtual classes; as subobjects of C12 they have nonzero storage requirements. Indeed, in the following program:

int main() {
    I2 * p2 = new C12; 
    I1 * p1 = reinterpret_cast<I1*>(p2);
    std::cout << p2 << '\n';
    std::cout << p1 << '\n';
    std::cout << dynamic_cast<I1*>(p2) << '\n';
    p1->nb1();
}

the output is:

0x14de0c8
0x14de0c8
0x14de0c0   // !!!
nb2         // !!!

You may be thinking of the empty base optimization (1.8p5); but this does not apply to classes with virtual methods, which require a vptr.

Source Link
ecatmur

The reinterpret_cast is unsafe; you should always use dynamic_cast. It is irrelevant that I1 and I2 are pure virtual classes; as subobjects of C12 they have nonzero storage requirements. Indeed, in the following program:

int main() {
    I2 * p2 = new C12; 
    I1 * p1 = reinterpret_cast<I1*>(p2);
    std::cout << p2 << '\n';
    std::cout << p1 << '\n';
    std::cout << dynamic_cast<I1*>(p2) << '\n';
    p1->nb1();
}

the output is:

0x14de0c8
0x14de0c8
0x14de0c0   // !!!
nb2         // !!!
lang-cpp