鉴于以下示例,为什么我必须明确使用该语句b->A::DoSomething()
而不仅仅是b->DoSomething()
?
编译器的重载决议不应该弄清楚我在谈论哪种方法?
我正在使用Microsoft VS 2005.(注意:在这种情况下使用虚拟无效.)
class A { public: int DoSomething() {return 0;}; }; class B : public A { public: int DoSomething(int x) {return 1;}; }; int main() { B* b = new B(); b->A::DoSomething(); //Why this? //b->DoSomething(); //Why not this? (Gives compiler error.) delete b; return 0; }
Konrad Rudol.. 41
两个"重载"不在同一范围内.默认情况下,编译器仅在找到名称匹配项之前才考虑可能的最小名称范围.参数匹配完成之后.在您的情况下,这意味着编译器看到B::DoSomething
.然后它尝试匹配参数列表,该列表失败.
一种解决方案是将过载从A
进入B
范围拉下来:
class B : public A { public: using A::DoSomething; // … }
@Chubsdad:这就是我把这个词放在引号中的原因.一旦该方法被拉入相同的范围,它就会变得过载. (4认同)
Pieter.. 14
重载分辨率是C++中最丑陋的部分之一
基本上,编译器在B的范围内找到名称匹配"DoSomething(int)",看到参数不匹配,并且因错误而停止.
可以通过使用B类中的A :: DoSomething来克服它
class A { public: int DoSomething() {return 0;} }; class B : public A { public: using A::DoSomething; int DoSomething(int x) {return 1;} }; int main(int argc, char** argv) { B* b = new B(); // b->A::DoSomething(); // still works, but... b->DoSomething(); // works now too delete b; return 0; }
Lehane.. 5
不,这种行为是存在的,以确保您不会被错误地从远程基类继承.
要绕过它,您需要通过在B类中放置一个使用A :: DoSomething来告诉编译器您要调用哪个方法.
有关此行为的快速简单概述,请参阅此文章.
两个"重载"不在同一范围内.默认情况下,编译器仅在找到名称匹配项之前才考虑可能的最小名称范围.参数匹配完成之后.在您的情况下,这意味着编译器看到B::DoSomething
.然后它尝试匹配参数列表,该列表失败.
一种解决方案是将过载从A
进入B
范围拉下来:
class B : public A { public: using A::DoSomething; // … }
重载分辨率是C++中最丑陋的部分之一
基本上,编译器在B的范围内找到名称匹配"DoSomething(int)",看到参数不匹配,并且因错误而停止.
可以通过使用B类中的A :: DoSomething来克服它
class A { public: int DoSomething() {return 0;} }; class B : public A { public: using A::DoSomething; int DoSomething(int x) {return 1;} }; int main(int argc, char** argv) { B* b = new B(); // b->A::DoSomething(); // still works, but... b->DoSomething(); // works now too delete b; return 0; }
不,这种行为是存在的,以确保您不会被错误地从远程基类继承.
要绕过它,您需要通过在B类中放置一个使用A :: DoSomething来告诉编译器您要调用哪个方法.
有关此行为的快速简单概述,请参阅此文章.
派生类中方法的存在会隐藏基类中具有相同名称(无论参数)的所有方法.这样做是为了避免这样的问题:
class A {} ; class B :public A { void DoSomething(long) {...} } B b; b.DoSomething(1); // calls B::DoSomething((long)1));
比以后有人改变了A类:
class A { void DoSomething(int ) {...} }
现在突然:
B b; b.DoSomething(1); // calls A::DoSomething(1);
换句话说,如果它不能像这样工作,那么你不能控制的类(A)中的无关变化可能会默默地影响代码的工作方式.