这是可移植C++代码吗?

Is this C++ code portable?

本文关键字:代码 C++ 可移植      更新时间:2023-10-16
struct A {
  int a;
  virtual void print() {}
};
struct B : A {
  int b;
  virtual void print() {}
};
int main(void)
{
  A *a = new B;
  a[0].print(); // g++, vs2010, clang call B::print.
}

所有三个 g++,vs2010,都调用 B::p rint。几乎怀疑我的C++101。我的印象是,在对象上使用点不会导致动态调度。只有带有指针的 -> 和带有引用的点才会产生动态调度。

所以我的问题是这段代码是否可移植?

a[0]

*a相同,并且该表达式是对A引用,并且虚拟调度通过引用发生,就像它通过指针一样。 a->print()(*a).print()是完全相同的。

它是可移植的。 a[0] 返回一个引用,引用也使用动态调度。

是的。相当于——

a->print();

它是可移植的,行为定义明确。 指针上的operator[]只执行指针算术和取消引用。它正在向指针添加0 * sizeof(A),因此从某种意义上说,这是一个"危险"的操作,因为任何其他值,但 0 会失败(在 B 数组上(,但由于 0 * sizeof(A( 为 0,在这种情况下,您可以,因为它添加了 0。

多态性适用于引用和指针。

a[0] 与指针一起使用是明确定义的,其含义与 *(a + 0) 相同。这就是内置[]运算符的工作方式。

关于编译器在没有多态性时不需要使用动态调度,您说得对了一部分。不过,这只是一个常见的优化,语言不需要。

当代码为

A a;
a.print();

编译器可以直接调用正确的函数,因为它可以在编译时告诉对象类型。