我遇到了一个可以简化为以下示例的问题:
#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()或用pa和fpa初始化reinterpret_cast<A*>(&c),而不仅仅是&c修复地址。
但我为什么要这么做?既然所有的继承都是公共的,那么在这种情况下,难道任何A*都不能将地址保存到任何A、B或C吗?为什么价值会隐式变化?我是否可以将警告标志传递给g++或clang++来警告这种行为?
发布于 2020-04-24 10:47:38
或用
reinterpret_cast<A*>(&c)初始化pa和fpa,而不仅仅是&c修复地址。
这并不能“修正”地址。那会破坏地址。它产生一个无效的指针。
,但我为什么要这么做呢?
你没必要那么做。偏移地址是基子对象的正确地址。
--如果涉及抽象类,为什么没有指向派生的指针和指向相同地址的指针?
因为在基本子对象之前有一些东西存储在对象中。
不应该有任何A*能够将地址保存到任何A、B或C
不是的。指向A的有效指针的地址总是A对象的地址。如果导出了动态类型,那么该对象就是基子对象。基可以存储在派生类开始时的偏移量处。
,因为所有继承都是公共的
在这方面,继承的可获得性与此无关。
以及是否有警告标志可以传递给g++或clang++来警告这种行为?
我非常怀疑是否会有。我也不明白为什么在这种情况下你会想要一个警告。
https://stackoverflow.com/questions/61406488
复制相似问题