我无法控制几个基类,例如:

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*:



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



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

  • 如果您确定BaseHost::getNode()返回指向MyNode对象的向上转换的指针,并且在类层次结构中没有虚拟继承,则可以。
  • 但是,如果BaseHost::getNode()会返回其他内容(例如,指向纯BaseNode或另一个BaseNode的同级衍生物的指针),则您将拥有UB。

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

    08-03 21:52