将基础实例指针转换为派生实例指针是否合法? (该实例不是派生实例)
is it legal to cast base-instance-pointer to derived-instance-pointer? (the instance is not a derived instance)
我想以不合格的方式(为什么?宏魔法)从 class 本身之外访问 Base
class 成员。该策略是在 Derived
class 中执行并将指向 Base
的指针转换为指向 Derived
的指针(即使实例不是 一个Derived
).
根据我的尝试,代码可以正确编译和运行:这是 标准 还是 意外 (和 UB 标准) ? coliru link
#include<iostream>
struct Base{
int a=3;
};
struct Derived: public Base{
int getA(){
// this scope has unqualified access to Base class members
return a;
}
};
int main(void){
Base b;
std::cerr<<((Derived*)(&b))->getA()<<std::endl;
}
如果 &b
指向的对象实际上不是 Derived
对象的子对象,则强制转换 (Derived*)(&b)
将等同于 static_cast<Derived*>(&b)
,后者具有未定义的行为。请参阅当前 C++ 标准草案的 [static.cast]/11(至少自 C++11 起就存在等效语言)。
您的程序因此具有未定义的行为,因为根本没有创建任何 Derived
对象并且 b
不是 Derived
对象的子对象。
请注意,cppreference page on static_cast
并未明确说明强制转换本身具有未定义的行为,但它具有,如上文所述。
我想您的代码 运行 会很好。因为它确实有 "a" 成员变量。
struct Derived: public Base{
int c;
int getA(){
// this scope has unqualified access to Base class members
return a;
}
int getC(){
return c;
}
};
int main(void){
Base b;
std::cerr<<((Derived*)(&b))->getC()<<std::endl;
}
上面的代码将 运行 出错,因为变量 "b" 中没有 "c" 成员,其类型是真正的 Base class。函数指针调用的函数getB,不属于任何实例变量,所以不符合。
我想以不合格的方式(为什么?宏魔法)从 class 本身之外访问 Base
class 成员。该策略是在 Derived
class 中执行并将指向 Base
的指针转换为指向 Derived
的指针(即使实例不是 一个Derived
).
根据我的尝试,代码可以正确编译和运行:这是 标准 还是 意外 (和 UB 标准) ? coliru link
#include<iostream>
struct Base{
int a=3;
};
struct Derived: public Base{
int getA(){
// this scope has unqualified access to Base class members
return a;
}
};
int main(void){
Base b;
std::cerr<<((Derived*)(&b))->getA()<<std::endl;
}
如果 &b
指向的对象实际上不是 Derived
对象的子对象,则强制转换 (Derived*)(&b)
将等同于 static_cast<Derived*>(&b)
,后者具有未定义的行为。请参阅当前 C++ 标准草案的 [static.cast]/11(至少自 C++11 起就存在等效语言)。
您的程序因此具有未定义的行为,因为根本没有创建任何 Derived
对象并且 b
不是 Derived
对象的子对象。
请注意,cppreference page on static_cast
并未明确说明强制转换本身具有未定义的行为,但它具有,如上文所述。
我想您的代码 运行 会很好。因为它确实有 "a" 成员变量。
struct Derived: public Base{
int c;
int getA(){
// this scope has unqualified access to Base class members
return a;
}
int getC(){
return c;
}
};
int main(void){
Base b;
std::cerr<<((Derived*)(&b))->getC()<<std::endl;
}
上面的代码将 运行 出错,因为变量 "b" 中没有 "c" 成员,其类型是真正的 Base class。函数指针调用的函数getB,不属于任何实例变量,所以不符合。