这个C++代码可以移植吗?

问题描述 投票:0回答:5
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、clang 都调用 B::print。几乎怀疑我的 C++ 101。我的印象是,对对象使用点不会导致动态调度。只有 -> 带有指针和带有引用的点才会导致动态调度。

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

c++ virtual portability
5个回答
14
投票

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


4
投票

它是便携式的。 a[0] 返回一个引用,引用也使用动态调度。


3
投票

是的。相当于-

a->print();

1
投票

它是可移植的并且行为是明确定义的。指针上的

operator[]
只是进行指针算术和取消引用。它将
0 * sizeof(A)
添加到指针,因此从某种意义上说,它是一个“危险”操作,因为除了 0 之外的任何其他值都会失败(在 B 数组上),但因为 0 * sizeof(A) 是 0,在此如果你没问题,因为它加了 0。

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


1
投票

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

关于编译器在没有多态性时不需要使用动态分派,您的说法部分正确。但这只是一种常见的优化,并不是语言所必需的。 当代码为

A a; a.print();

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

© www.soinside.com 2019 - 2024. All rights reserved.