【问题标题】:is it legal to cast base-instance-pointer to derived-instance-pointer? (the instance is not a derived instance)将基实例指针转换为派生实例指针是否合法? (实例不是派生实例)
【发布时间】:2020-04-07 12:38:26
【问题描述】:

我想以非限定方式(为什么?宏巫术)从班级本身外部访问Base 班级成员。策略是在Derived 类中执行此操作,并将指向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;
}

【问题讨论】:

  • 您想要一个language-lawyer 类型的答案(引用标准)还是引用cppreference.com 就足够了?
  • 访问私有成员有合法途径:stackoverflow.com/questions/22624503/…
  • @JaMiT:即使编译器变得更智能,我也需要实现无法工作,所以语言律师类型的答案让我保证它在未来不会中断。
  • @AlanBirtles:我不需要访问私有成员(它们都是公共的),但我需要在类范围之外进行非限定访问。
  • 也许真正的问题是宏魔法。

标签: c++ pointers inheritance casting downcast


【解决方案1】:

如果&amp;b 指向的对象实际上不是Derived 对象的子对象,则转换(Derived*)(&amp;b) 将等效于具有未定义行为的static_cast&lt;Derived*&gt;(&amp;b)。请参阅当前 C++ 标准草案的[static.cast]/11(等效语言至少从 C++11 开始就存在)。

因此,您的程序具有未定义的行为,因为根本没有创建任何 Derived 对象,并且 b 不是 Derived 对象的子对象。

请注意,cppreference page on static_cast 并未明确说明强制转换本身具有未定义的行为,但正如上面引用的那样。

【讨论】:

  • 谢谢!在类范围之外直接访问成员的任何其他方式? (friendusing 魔法或类似的东西?)
  • @eudoxos 我想引用声明auto&amp; a = b.a; 不符合您的要求?目前我没有更好的建议。调用不存在对象的成员函数在任何一种情况下都不起作用,即使您设法以某种方式在没有 UB 的情况下获得了正确类型的指针。
  • 关于引用的好点,我只需要使用额外的预处理器魔法一一声明它们;)
【解决方案2】:

我猜你的代码会运行良好。因为它确实有“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”成员,其类型是真正的基类。函数指针调用的函数getB,它不属于任何实例变量,所以不会发生。

【讨论】:

  • 是的,它会运行,但它是合法正确的代码吗?这就是问题所在。
  • 不推荐,因为 (a) 可读性低,(b) 演员表是危险的,(c) 当你不小心使用 getC 函数时容易出错。从理论上讲,您可以通过地址访问任何变量,或者如果您清楚,可以强制强制访问,但这是一个非常糟糕的主意。
  • 其实是合法的。
  • 你能说说为什么吗? stackoverflow.com/a/59333141/761090 与您相矛盾,他引用了显示它是 UB 的标准。我用“legal”来表示“not-UB”;您是指其他方式吗,例如可解析或可编译?
  • 嗯...If B is a virtual base class of D or a base class of a virtual base class of D, or if no valid standard conversion from “pointer to D” to “pointer to B” exists ([conv.ptr]), the program is ill-formed. ...Otherwise, the behavior is undefined. 很抱歉,这里的讨论无处可去。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 2018-10-18
  • 2011-11-05
  • 2013-02-12
  • 1970-01-01
相关资源
最近更新 更多