我有两个类(A0和A1),它们具有一个函数foo(),而一个A0具有一个函数bar(),它仅调用foo()。还有从A0和A1继承的B类。
B除了从A0和A1继承外,什么也不做。
为什么在呼叫B->bar()
时没有歧义?
一个小代码示例
class A0
{
protected:
/*virtual*/ void foo() {std::cout << "A0" << std::endl; }
public:
void bar() {foo(); }
};
class A1
{
protected:
/*virtual*/ void foo() {std::cout << "A1" << std::endl; }
};
class B : public A0, public A1
{
protected:
//virtual void foo() override {A1::foo(); }
};
int main()
{
B *lPtr = new B;
lPtr->bar(); //"A0" without the override, "A1" with the override
delete lPtr;
return 0;
}
如果我取消注释虚拟和函数覆盖,仍然没有歧义,但会调用另一个foo。
为什么仍然没有歧义,为什么又称另一个歧义?
答案 0 :(得分:0)
如果您有virtual
,则您的vtable中有两个foo
。
第一个是A0::foo
,第二个是A1::foo
。
当您覆盖foo
中的B
时,您覆盖两个 ,并指示它调用A1::foo()
。
如果您未覆盖foo
中的B
,则两个foo
将保留在vtable中,除了名称以外,它们不相关。
在A0::bar
中,当您调用foo()
时,它将在本地查找foo
。它看到一个-A0::foo
-是虚拟的。因此,它将调用编码到vtable中以执行A0::foo
。
在B
中没有覆盖,调用A0::foo
。借助B
中的覆盖,它会在调用B::foo
时调用A1::foo
。
在您没有virtual
的情况下,除了vtable
位之外,其他条件相同。
您有两个功能A0::foo
和A1::foo
。通过指向A0
的指针,->foo()
调用A0::foo
。
B
具有指向->foo()
的指针。
如果您编写了B::foo
方法(无论它是虚拟的都没关系),则B->foo()
会调用它。
两个事物共享一个名称的事实并不意味着它们是同一事物,也不会使所有调用变得模棱两可。
仅当您无法从上下文中命名哪个调用时,这些调用才是模棱两可的。