【问题标题】:C++ Why isn't the second expression valid?C++ 为什么第二个表达式无效?
【发布时间】:2012-10-03 04:07:42
【问题描述】:

假设您有以下对象层次结构:

class Vehicle {
public:
  virtual ~Vehicle() {}
};
class LandCraft: public Vehicle {};
class Truck: public LandCraft {};

现在,我们有两个表达式:

Truck truck;
Vehicle& vehicle = truck;

根据一个作业的解决方案,第二个表达式无效。但为什么?我的编译器根本没有抱怨,我看不出这里应该有什么问题。

【问题讨论】:

  • 哪个编译器?您是否尝试过 -pedantic 标志(或等效标志)?
  • 对我来说似乎也是正确的,因为您通过使用对 Vehicle (stackoverflow.com/questions/2822146/…) 的引用来避免“切片”问题。
  • 我觉得不错。这个问题实际上使用Vehicle&吗?如果它只使用Vehicle,那么你就会遇到切片问题。
  • 在 pedantic 上编译得很好,我看不出有任何问题。
  • 车辆类定义需要分号。

标签: c++


【解决方案1】:

听起来作业解决方案不正确。从派生的实例初始化对基类型的引用并没有错。

编辑

正如一些人所指出的(尤其是 Slaks),虽然这句话本身并没有错,但它确实为未来的错误提供了可能性。它允许您任意将任何Vehicle 放入需要Truck 的位置。例如考虑以下

Truck truck;
Vehicle& reallyATruck = truck;
reallyATruck = LandCraft();

哎呀!

【讨论】:

  • 我没有看到任何不安全的地方。这只是一个切片问题,与引用无关,只是多态性。
【解决方案2】:

第二个表达式完全有效。您可能误解了解决方案所说的内容。也许不是说它在语法上无效,而是有其他问题。

当您使用的类没有虚函数时,这样做似乎有点奇怪和可疑。

我的倾向是家庭作业解决方案完全是错误的。但是这么简单的错误,它似乎很奇怪。

【讨论】:

    【解决方案3】:

    抱歉,我已验证您的代码在 Visual Studio 2010 中运行良好,只是您在 Vehicle 类的末尾漏掉了一个分号。

    【讨论】:

      【解决方案4】:

      SLaks 解释了为什么该表达式不安全,但它是合法的。

      根据 Comeau 的说法,唯一的错误是 class Vehicle {} /* HERE */ 末尾缺少分号。

      【讨论】:

      • @SLaks:在您编辑后它是正确的,我希望人们开始扭转他们的反对意见。
      • 该表达式无论如何都不是不安全的,实际上在参数传递中被广泛使用。您可以切片不同类型的对象(SLaks 演示过)这一事实与表达式无关。为了清楚起见,我只在编辑后阅读了 SLaks 的答案,并出于这个特殊原因投了反对票。
      • @David:正如我评论 SLaks 的答案,引用和指针只有在目标是 const 时才是安全协变的(考虑到指针,而不是对象)。只读接口是协变的,只写接口是逆变的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多