c++ - 对象切片或 UB 风险?

标签 c++ inheritance undefined-behavior

有几个基类是我无法控制的:-

class BaseNode // Just a POD class. No VTable
{
  void foo();
}

class BaseHost 
{
public:
  BaseNode *getNode()
  {
    ...
  } 
}

我想“扩展”BaseNode::foo 的功能,但该类实际上是密封的。

建议如下:-

class MyNode: public BaseNode 
{
  void foo()
  {
    // do my stuff..., then
    BaseNode::foo();
  }    
}

class MyHost: public BaseHost 
{
public:
  MyNode *getNode()
  {
    return (MyNode*) BaseHost::getNode(); // Slicing or UB risk?
  }   
}

如果 MyNode 引入额外的类成员或虚拟方法,事情就会变得很糟糕——但如果满足这些约束,我还有 UB 吗?

任何其他问题,或者我是否完全重新考虑设计?

最佳答案

这种向下转型要格外小心:它很容易导致 UB。

标准保证您可以安全地从 MyNode* 转换为 BaseNode*:

4.10/3: A prvalue of type “pointer to cv D”, where D is a class type, can be converted to a prvalue of type “pointer to cv B”, where B is a base class of D. If B is an inaccessible or ambiguous base class of D, a program that necessitates this conversion is ill-formed. The result of the conversion is a pointer to the base class subobject of the derived class object. The null pointer value is converted to the null pointer value of the destination type.

但让我们玩火:标准还允许您在特定条件下从 BaseNode* 转换为 MyNode* :

5.2.9/11: A prvalue of type “pointer to cv1 B,” where B is a class type, can be converted to a prvalue of type “pointer to cv2 D,” where D is a class derived from B, if a valid standard conversion from “pointer to D” to “pointer to B” exists, cv2 is the same cv-qualification as, or greater cv-qualification than, cv1, and B is neither a virtual base class of D nor a base class of a virtual base class of D. The null pointer value is converted to the null pointer value of the destination type. If the prvalue of type “pointer to cv1 B” points to a B that is actually a subobject of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the behavior is undefined

我尝试将这些引用翻译成纯文本:

  • 如果您确定 BaseHost::getNode() 返回指向 MyNode 对象的向上转换指针,并且您的类层次结构中没有虚拟继承,那么它是好的。
  • 但是如果 BaseHost::getNode() 会返回其他东西(例如,指向普通 BaseNodeBaseNode 的另一个同级派生的指针>) 你将拥有 UB。

如前所述,这很危险:UB 可能已经在指针转换期间发生,甚至在您尝试取消引用指针之前。所以最好尽量避免它。如果你有一个多态的 BaseNode 类(例如,使用虚拟析构函数),你可以使用更安全的 dynamic_cast .

关于c++ - 对象切片或 UB 风险?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38038122/

相关文章:

c++ - 多态覆盖

c++ - 将指针强制转换为整数、递增该整数,然后强制转换回来是否安全?

c - 返回复合文字

c++ - 如何继承静态成员?

c++ - 为新文件类型重载 >> 运算符的优雅方法是什么?

c - 为什么这个 for 循环在某些平台上退出,而在其他平台上不退出?

c++ - 在 C++ 中添加到集合之前或之后

C++ 大型二维数组访问冲突

c++ - VC++ 6 项目迁移到 VC++ 2008 时出现模板类编译错误

c++ - boost::variant 是否支持 64 位整数?