你的B级没有overrideA 中的成员函数,它超载它。或者尝试无论如何,稍后再看看有关隐藏的内容。
重写是指派生类从基类定义其自己的虚拟成员函数版本。重载是指定义具有相同名称的不同函数。
当对具有基类类型的指针或引用进行虚拟调用时,它只会“考虑”派生类中的重写,而不是重载。这是至关重要的 - 对于调用者对待 B 的实例来说,就好像它做了 A 可以做的所有事情(这是动态多态性和虚函数的要点),它的hello
函数需要能够接受 A 类型的任何对象。hello
仅接受 B 类型对象而不是任何 A 类型对象的函数更具限制性。发挥不了A的作用hello
函数,所以它不是覆盖。
如果你尝试一下打电话hello
在 A 和 B 上,传递 A 或 B 类型的对象,您应该能够看到差异。 A 有一个接受 A 的函数(您尚未定义该函数,因此如果您调用它,那么您的程序将无法链接,但您可以修复该问题)。 B 有一个采用 B 的函数。它们碰巧具有相同的名称,当然,由于 B 派生自 A,因此您可以将 B 传递给采用 A 的函数。但是 B 的函数在虚拟调用中不充当覆盖。
可以在 B 对象上调用 A 的函数,但只能通过 A 的引用或指针。C++ 的一个功能是定义hello
B 中隐藏了 A 中的定义。如果您想要重载,可以通过添加来取消隐藏基类函数using A::hello;
到 B 类。如果您想要覆盖,则必须定义一个采用相同参数的函数。例如:
#include <iostream>
class A
{
public:
virtual int hello(A a) {std::cout << "A\n"; }
virtual int foo(int i) { std::cout << "A::Foo " << i << "\n"; }
};
class B : public A
{
public:
using A::hello;
// here's an overload
int hello(B b){ std::cout << "B\n"; };
// here's an override:
virtual int foo(int i) { std::cout << "B::Foo " << i << "\n"; }
};
int main() {
A a;
B b;
a.hello(a); // calls the function exactly as defined in A
a.hello(b); // B "is an" A, so this is allowed and slices the parameter
b.hello(a); // OK, but only because of `using`
b.hello(b); // calls the function exactly as defined in B
A &ab = b; // a reference to a B object, but as an A
ab.hello(a); // calls the function in A
ab.hello(b); // *also* calls the function in A, proving B has not overridden it
a.foo(1); // calls the function in A
b.foo(2); // calls the function in B
ab.foo(3); // calls the function in B, because it is overridden
}
Output:
A
A
A
B
A
A
A::Foo 1
B::Foo 2
B::Foo 3
如果你拿走using A::hello;
来自 B 的线路,然后呼叫b.hello(a);
编译失败:
error: no matching function for call to `B::hello(A&)'
note: candidates are: int B::hello(B)