17

我希望标题实际上描述了我想问的...

我写了一段代码,用 gcc 编译并按我的预期工作。但是,它不能使用 llvm 编译,并且使用 icc 编译时代码的执行方式不同!
这是问题的一个例子:

#include <iostream>

using std::cout; using std::endl;

class A {
public:
  virtual void foo() { cout << "A::foo()" << endl; }
};

class B : public A {
public:
  typedef A  base;
  virtual void foo() { cout << "B::foo()" << endl; }
};

int main() {
  typedef B  base;
  base* bp = new B();
  bp->base::foo(); 
}

gcc 输出:A::foo()
icc 输出:B::foo()

有人能解释一下标准对这个案子有什么看法吗?

4

2 回答 2

7

从 C++11,§3.4.5/4 开始:

如果类成员访问中的 id-expression 是以下形式的限定 id
    类名或命名空间名::...
. 后面的类名或命名空间名。或 -> 运算符首先在对象表达式的类中查找,如果找到,则使用名称。否则在整个后缀表达式的上下文中查找它。

我不认为它可以更清楚。这找到了B::base,所以输出应该是A::foo()

于 2012-06-20T09:04:34.853 回答
6

我认为标准的这一部分是相关的:

3.4.3.1 类成员 [class.qual]

1) 如果限定标识的嵌套名称说明符指定了一个类,则在该类的范围内查找嵌套名称说明符之后指定的名称 (10.2),但下面列出的情况除外。该名称应代表该类或其基类之一的一个或多个成员(第 10 条)。[注意:可以在其潜在范围(3.3.7)中的任何点使用限定ID来引用类成员。—尾注] 上述名称查找规则的例外情况如下:

— 按照 3.4.3 中的规定查找析构函数名称;

— 以与类成员访问中的转换类型 ID 相同的方式查找转换函数 ID 的转换类型 ID(见 3.4.5);

— 在整个后缀表达式出现的上下文中查找模板 ID 的模板参数中的名称。

— 在 using-declaration (7.3.3) 中指定的名称的查找也找到隐藏在同一范围内的类或枚举名称 (3.3.10)。

base::在这种情况下,似乎“提名”了一个班级,因此查找是在班级范围内完成的。我看不出任何异常情况如何适用,所以它是类的范围,因此base相当于A.

(5.1.1-8 表示在这种情况下它是一个限定 ID,并且适用 3.4.3.1)

于 2012-06-20T08:50:18.643 回答