【问题标题】:Const casting empty base classconst 铸造空基类
【发布时间】:2018-06-03 19:13:10
【问题描述】:

const_cast 离开一个空的基类并在其上调用非 const 方法是未定义的行为吗?例如

class EmptyBase {
public:
    void bar() { ... }
};

class Something : public EmptyBase {
public:
    void foo() const {
        const_cast<EmptyBase&>(static_cast<const EmptyBase&>(*this)).bar();
   }
};

我无法在标准(C++14 和 C++17)中找到相关信息来回答这个问题..

【问题讨论】:

  • 你的意思是EmptyBase::bar(); in void foo() const
  • 所以::bar 实际上是一个静态成员函数?
  • 参见“7.1.6.1 cv-qualifiers”,第 4 句。它给出了例子。
  • @NonStatic 不是真的,已编辑
  • @Lanting ^ 不,一个成员函数

标签: c++ c++14 language-lawyer c++17 const-cast


【解决方案1】:

它本身不是 UB。当你抛弃 constness 并使用获得的 glvalue 来修改最初声明为 const 的对象时,你会得到未定义的行为。这是对此的标准报价 ([dcl.type.cv]/4):

除了声明为 mutable 的任何类成员都可以修改外,任何 尝试在其生命周期内修改 const 对象会导致 未定义的行为。

仅仅调用成员函数并不是对对象的修改。这完全取决于函数做什么。所以如果它做了一些疯狂的事情,比如:

std::memset(this, 0, sizeof(*this));

这肯定会导致未定义的行为。但假设它没有,并且由于 没有成员 可以以不正确的方式进行修改,因此调用中没有 UB。

另一个问题,是否是一个好主意,有一个明显的答案。常量转换不应该乱扔代码库。但是,如果基类行为良好,尽管定义不明确,但您无法更改类可能是可以接受的。

【讨论】:

  • 在这种情况下this 不会是EmptyBase*sizeof(*this) 不会是 0?
  • @n.caillou - 否。sizeof 可能不会为格式良好的程序中的任何对象类型返回 0。在成员函数内部,它会将*this 视为“完整”对象。所以sizeof 可能会返回 1。实际上,这意味着你将在Something 的记忆中翻腾。
  • 我明白了。我找到了相关的en.cppreference.com/w/cpp/language/ebo
猜你喜欢
  • 2011-04-03
  • 2013-01-25
  • 2011-03-26
  • 2011-03-09
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多