C++载的决议[重复]
-
09-06-2019 - |
题
这个问题已经有一个答案在这里:
下面给出的例子,为什么我要明确地使用的声明 b->A::DoSomething()
而不是只是 b->DoSomething()
?
不应该编译器的过载决议找出这方法我在说什么?
我使用了微软VS2005年。(注:使用虚拟不会帮助在这种情况。)
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;
}
解决方案
两个"超载"不在同一范围。默认情况下,编译器只考虑最小的可能名称的范围,直到找到一个名称匹配。参匹配 之后.在你的情况这意味着,编译器看到 B::DoSomething
.然后,它试图匹配参数清单,它失败。
一种解决办法就是要拉下载从 A
入 B
's范围:
class B : public A {
public:
using A::DoSomething;
// …
}
其他提示
载的决议是一项丑陋的部分C++
基本上编译器发现一个名称匹配"或重写现有的(int)"的范围B,认为的参数不符,并且停止一个错误。
它可以克服的,通过使用A::或重写现在B类
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;
}
存在的一个方法中的一个源类隐藏的所有方法与名称相同(不论的参数),在基础课程。这样做是为了避免类似这样的问题:
class A {} ;
class B :public A
{
void DoSomething(long) {...}
}
B b;
b.DoSomething(1); // calls B::DoSomething((long)1));
比以后别人的更改类:
class A
{
void DoSomething(int ) {...}
}
现在突然
B b;
b.DoSomething(1); // calls A::DoSomething(1);
换句话说,如果它没有这样的工作,一个无关的变化的一类,你不能控制的(A)、可以默默如何影响你的代码的工作。
这有什么用的方式的名称号决议的工作。基本上,我们第一个找到的范围,从它的名称来,然后我们收集所有的重载这一名称在这一范围。但是,范围在你的情况是B类,并在B类、B::或重写现 隐藏 A::或重写现有的:
3.3.7名躲藏的[基本的。范围。隐藏]
...[喀嚓]...
3在件的功能定义,《宣言》的一个当地的名字隐藏 《宣言》的一个成员类用相同的名称;看看 basic.scope.class.《宣言》的一个成员在得出类 (类。衍生的)隐藏宣言》的一个成员的基类的 相同的名称;看看 类。部件。查找.
因为名躲藏,A::或重写现有的甚至没有考虑过载决议
在定义中的一个函数的一个源类然后它隐藏了所有的功能与该名称在基类。如果基类功能是虚拟的和具有兼容签名然后派生类功能也复盖基类功能。然而,这并不影响知名度。
你可以让基类功能,可见,与一个采用宣言:
class B : public A
{
public:
int DoSomething(int x) {return 1;};
using A::DoSomething;
};
不过载!这就是隐藏!
当搜索的继承树的功能,使用C++使用的名称不参数,一旦发现任何定义,它停止,然后探讨的论点。在给出的例子,它停止在B类为了能够做什么,你是后,B类的定义应该是这样的:
class B : public A
{
public:
using A::DoSomething;
int DoSomething(int x) {return 1;};
};
功能是隐藏的功能与名称相同的亚类(但有一个不同的签名)。你可以取消它的使用使用的语句,如在使用::或重写现有的();