c – 为什么允许冗余类名限定符?
我遇到了一些这样的代码:
struct A { A() {} A(int) {} }; struct B : A { void init(int i); }; void B::init(int i) { A::A(i); // what is this? } int main() { B b; b.init(2); } 这个编译并运行使用VC11 beta,没有错误或警告与/ W4. 明显的目的是调用B :: init来重新初始化B的A基本子对象.我相信它实际上解析为一个名为i的类型为A的变量声明.使用clang编译生成诊断: ConsoleApplication1.cpp:11:14: warning: declaration shadows a local variable A::A(i); ^ ConsoleApplication1.cpp:10:22: note: previous declaration is here void B::init(int i) { ^ ConsoleApplication1.cpp:11:14: error: redefinition of 'i' with a different type A::A(i); ^ ConsoleApplication1.cpp:10:22: note: previous definition is here void B::init(int i) { ^ 看起来好奇的是,可以使用冗余类资格来引用该类型. 此外,A :: A(i)似乎被VS11和clang / gcc不同的解析.如果我做A :: A(b)clang和gcc使用默认构造函数创建类型A的变量b.这个说法的VS11错误是一个未知的标识符.使用构造函数A :: A(int)创建一个临时的A作为参数,VS11似乎解析A :: A(i).当冗余限定符被消除时,将解析源作为变量声明,如clang和gcc do,并产生一个类似的错误,关于阴影变量i. 解析这个差异解释了为什么VS11会扼制多于一个额外的限定词; A :: A :: A :: A(i),为什么,由于clang和gcc可以接受一个额外的限定词,任何多于一个的数字与一个额外的结果相同. 这是另一个上下文中冗余限定词的另一个例子.所有编译器似乎都将其解析为临时构造: class Foo {}; void bar(Foo const &) {} int main() { bar(Foo::Foo()); } >为什么允许冗余限定词? 解决方法
虽然这种现象可能归因于类名注入,正如在ephemient的答案中所指出的,对于这个具体的例子,C语言已经被非法使用了.
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#147 组合A :: A需要引用类构造函数,而不是类注入的名称. A :: A(i)应该被兼容的编译器解释为涉及构造函数名称的非法(因此是无意义的)表达式.例如,Comeau编译器将拒绝编译您的代码. 显然,VC11继续将A :: A作为注入类名的参考.有趣的是,我在VS2005中没有观察到这个问题. 在A :: A被解释为指向注入名称的那一天,可以声明一个A对象 A::A::A::A::A::A a; 等等,任意数量的As.但不再是令人惊讶的是,由Ideaone使用的GCC版本(4.3.4?)仍然受到这个问题的困扰 http://ideone.com/OkR0F 您可以尝试使用您的VC11版本,看看它是否允许. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |