如果涉及抽象 类,为什么指向派生的指针和指向基的指针不指向同一地址?
Why doesn't a pointer to derived and a pointer to base point to the same address if abstract classes are involved?
我遇到了一个可以简化为以下示例的问题:
#include "iostream"
struct A {
char a;
};
struct B : A {
virtual void f() = 0;
};
struct C : B {
void f() override {}
};
void f(A* fpa) {
std::cout << fpa << '\n' << reinterpret_cast<C*>(fpa) << std::endl;
}
int main() {
C c {};
A* pa {&c};
std::cout << &c << '\n' << pa << '\n' << reinterpret_cast<C*>(pa) << std::endl;
f(&c);
}
pa
和 fpa
都没有继续指向 c
的地址,尽管它们都被 &c
初始化。在 &c
之后打印的所有地址都直接偏移 +8(用 g++ 和 clang++ 测试)。删除 A::a 或 B::f() 和 C::f() 或使用 reinterpret_cast<A*>(&c)
而不是 &c
初始化 pa
和 fpa
修复地址。
但为什么我必须这样做?在这种情况下,任何 A*
不应该能够保存任何 A
、B
或 C
的地址,因为所有继承都是 public 吗?为什么值会隐式改变?是否有我可以传递给 g++ 或 clang++ 的警告标志来警告这种行为?
or initializing pa and fpa with reinterpret_cast<A*>(&c)
instead of just &c
fixes the addresses.
那不是 "fix" 地址。 破坏了地址。它产生一个无效的指针。
But why do I have to do that?
您不必那样做。偏移地址是基础子对象的正确地址。
Why doesn't a pointer to derived and a pointer to base point to the same address if abstract classes are involved?
因为在基础子对象之前的对象中存储了一些东西。
Shouldn't any A* be able to hold the address to any A, B, or C
没有。指向 A 的有效指针的地址始终是 A 对象的地址。如果动态类型是派生的,则该 A 对象是基础子对象。基数可以存储在距派生 class.
开头的偏移处
since all inheritance is public
继承的可访问性与此无关。
And are there warning flags I can pass to g++ or clang++ that warn about this kind of behavior?
我非常怀疑会有。我也不明白你为什么要在这种情况下发出警告。
我遇到了一个可以简化为以下示例的问题:
#include "iostream"
struct A {
char a;
};
struct B : A {
virtual void f() = 0;
};
struct C : B {
void f() override {}
};
void f(A* fpa) {
std::cout << fpa << '\n' << reinterpret_cast<C*>(fpa) << std::endl;
}
int main() {
C c {};
A* pa {&c};
std::cout << &c << '\n' << pa << '\n' << reinterpret_cast<C*>(pa) << std::endl;
f(&c);
}
pa
和 fpa
都没有继续指向 c
的地址,尽管它们都被 &c
初始化。在 &c
之后打印的所有地址都直接偏移 +8(用 g++ 和 clang++ 测试)。删除 A::a 或 B::f() 和 C::f() 或使用 reinterpret_cast<A*>(&c)
而不是 &c
初始化 pa
和 fpa
修复地址。
但为什么我必须这样做?在这种情况下,任何 A*
不应该能够保存任何 A
、B
或 C
的地址,因为所有继承都是 public 吗?为什么值会隐式改变?是否有我可以传递给 g++ 或 clang++ 的警告标志来警告这种行为?
or initializing pa and fpa with
reinterpret_cast<A*>(&c)
instead of just&c
fixes the addresses.
那不是 "fix" 地址。 破坏了地址。它产生一个无效的指针。
But why do I have to do that?
您不必那样做。偏移地址是基础子对象的正确地址。
Why doesn't a pointer to derived and a pointer to base point to the same address if abstract classes are involved?
因为在基础子对象之前的对象中存储了一些东西。
Shouldn't any A* be able to hold the address to any A, B, or C
没有。指向 A 的有效指针的地址始终是 A 对象的地址。如果动态类型是派生的,则该 A 对象是基础子对象。基数可以存储在距派生 class.
开头的偏移处since all inheritance is public
继承的可访问性与此无关。
And are there warning flags I can pass to g++ or clang++ that warn about this kind of behavior?
我非常怀疑会有。我也不明白你为什么要在这种情况下发出警告。