根据C++ 2017标准(10.1.2函数说明符):
2 virtual关键字只能在非静态类成员函数的初始声明中使用;请参见13.3。
而且(13.3虚函数):
2 如果在类Base和派生自Base的直接或间接类Derived中声明了一个名为vf的虚成员函数,其参数类型列表(11.3.5)、cv限定符和引用限定符(或缺乏它们)与Base::vf相同,则声明Derived::vf时会覆盖111 Base::vf,并且Derived::vf也是虚的(无论是否这样声明)。为了方便起见,我们说任何虚函数都是覆盖它本身。类对象S的虚成员函数C::vf是最终覆盖者,除非S所属的最派生类(4.5)声明或继承了另一个覆盖vf的成员函数。在派生类中,如果基类子对象的虚成员函数有多个最终覆盖者,则程序是非法的。
因此,在类B中,函数show是虚函数,因为它具有与类A中声明的函数相同的签名。
考虑一个更有趣的例子,当在类B中将限定符const添加到成员函数show时。
#include<iostream>
using namespace std;
class A {
public:
virtual void show(){
cout << "A \n";
}
};
class B : public A {
public:
void show() const{
cout << "B \n";
}
};
class C : public B {
public:
void show() {
cout << "C \n";
}
};
int main(){
A *ab = new B;
A *ac = new C;
B *bc = new C;
ab->show();
ac->show();
bc->show();
}
在这种情况下,输出将类似于:
A
C
B
在这个表达式语句中
ab->show();
在类A中声明了一个名为show的虚函数。在这个语句中,保留了html标签。
ac->show();
在类C中覆盖了一个叫做相同的虚函数。编译器使用类A中的虚函数声明,因为指针ac的静态类型是A *。
在这个语句中:
bc->show();
存在一个被称为非虚成员函数show
,其有限定符const
。这是因为指针bc
的静态类型为B *
,编译器在类B
中找到了隐藏在类A
中声明的虚函数。
对于原始程序,您可以使用关键字override
来使类定义更加清晰。例如:
#include<iostream>
using namespace std;
class A {
public:
virtual void show(){
cout << "A \n";
}
};
class B : public A {
public:
void show() override{
cout << "B \n";
}
};
class C : public B {
public:
void show() override{
cout << "C \n";
}
};
int main(){
A *ab = new B;
A *ac = new C;
B *bc = new C;
ab->show();
ac->show();
bc->show();
}
B
中的show()
函数是虚函数,因为它继承自A
,而A
的show()
函数也是虚函数。 - Peter