2012-06-20 42 views
18

我希望标题实际上描述了什么我想问问...C++方法调用和类型范围分辨率歧义

我写了一张与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的()

有人能解释一下什么是标准说一下这个案例?

+5

我想说这是GCC和ICC中的一个错误,因为'B :: base'不是''B''的_member_,这意味着它不可能作为一个成员来访问它('bp-> base')。 –

+1

我同意@JoachimPileborg,而且在这个范围内'base'可以被解释为B.你有警告标志编译? (-gall for gcc) – Geoffroy

+1

这不就是未定义的行为,因为'main'不是必需的形式吗?看起来所有的编译器都是正确的。 –

回答

7

从C++ 11,§3.4.5/ 4:

如果类成员访问中的id表达式是 表
 
    class-name-or-namespace-name::... 
的限定标识,则类名或命名空间名称 后面的。或 - >运算符首先在 对象表达式的类中查找,并使用名称(如果找到)。否则,在整个postfix-expression的上下文中查找 。

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

+0

谢谢你的帮助,你们真棒。这个特定的段落确实非常清楚并且恰到好处! – Nowakus

6

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

3.4.3.1类成员[class.qual]

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

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

- conversion-type-id的转换类型id在类成员访问(见3.4.5)中以与 conversion-type-id相同的方式查找;

- 在模板ID的模板参数中的名称 在整个后缀表达式发生的上下文 中查找。

- 在使用声明(7.3.3)中指定的名称 的查找也找到隐藏在相同范围(3.3.10)中的枚举类名或 枚举名。

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

(5.1.1-8表示它是一个合格的-ID在这种情况下,并且3.4.3.1内)

+0

同意。这对我来说似乎也很清楚。代码是正确的,定义良好,输出应该是'A :: foo'。 –