1

我很好奇将指针转换为派生类和基类实际上是如何工作的。这是一个例子:

struct A {};
struct B : A {};

// Boxing a pointer to an instance of B
void* p = new B();

现在,假设我想通过指针 p 访问 A 的可能成员或方法。

A* a1 = (A*)p;
A* a2 = (A*)((B*)p);

哪一个是正确的?有什么区别吗?
你能告诉我在哪里可以获得关于这个主题的更多信息吗?

4

1 回答 1

2

在这种情况下,实践上没有区别。

但是如果有多重继承可能会有区别:

#include <cstdio>

struct A { int x; };
struct B { int y; };

struct C : B, A {};

int main() {
    void* c = new C();
    printf("%p\n", c);             // 0x1000
    printf("%p\n", (A*) c);        // 0x1000
    printf("%p\n", (A*) ((C*) c)); // 0x1004
    return 0;
}

或者子类有虚拟方法但父类没有[1],包括使用虚拟继承[2]

就标准而言,由于 OP 使用 C 风格转换,在这种情况下相当于static_cast.

转换序列B*void*B*A*是有效的,其中前两个转换将返回与 §5.2.9[expr.static.cast]/13 要求的相同的指针,最后一个转换用作指针转换 §4.10[conv .ptr]/3。

但是,强制转换序列B*void*A*实际上会给出未定义的结果,因为在 §5.2.9/13 ☺ 中没有定义结果。


[1]

#include <cstdio>

struct A { int x; };
struct C : A { virtual void g() {} };

int main() {
    void* c = new C();
    printf("%p\n", c);              // 0x1000
    printf("%p\n", (A*) c);         // 0x1000
    printf("%p\n", (A*) ((C*) c));  // 0x1008
    return 0;
}

[2]

#include <cstdio>

struct A { int x; };
struct C : virtual A {};

int main() {
    void* c = new C();
    printf("%p\n", c);              // 0x1000
    printf("%p\n", (A*) c);         // 0x1000
    printf("%p\n", (A*) ((C*) c));  // 0x1008
    return 0;
}
于 2012-08-12T12:43:02.293 回答