与C++中的虚拟关键字混淆
Confusion with virtual keyword in C++
我正在研究virtual
关键字在C++的效果,我想出了这个代码。
#include<iostream>
using namespace std;
class A {
public:
virtual void show(){
cout << "A n";
}
};
class B : public A {
public:
void show(){
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();
}
预期输出为:
B
C
B
由于 B 中的show
函数是非虚拟的。但是编译时的结果是:
B
C
C
它的行为就好像 B 中的show
函数是虚拟的。为什么会这样呢?B类在这里被覆盖了吗?如果我将 C 类指向 B 类,为什么我会指向 A 类?
根据 2017 C++标准(10.1.2 函数说明符)
2 虚拟说明符只能在初始声明中使用 非静态类成员函数;参见 13.3.
和(13.3 虚拟函数)
2如果虚成员函数 vf 在类 Base 和 一个类 派生的,直接或间接派生自 Base,一个成员 同名函数 VF,参数类型列表 (11.3.5), cv-qualifion,和ref-qualifier(或没有相同)作为Base::vf 被声明,则派生::vf 也是虚拟的(无论是否如此) 声明),它覆盖 111 Base::vf。为了方便起见,我们说 任何虚拟函数都会覆盖自身。虚拟成员函数 C::vf 类对象 S 是最终覆盖器,除非派生最多的类 (4.5) 其中 S 是基类子对象(如果有的话)声明或 继承另一个重写 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
称为虚函数。
在此声明中
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();
}
如果在base
类中指定,则无需将函数指定为派生类中的virtual
函数。
行为是正确的。由于show
函数是虚拟的,因此调用的版本将是附加到要调用它的实例的版本,而不是由该实例的类型(可以是该实例的实际类型的基础)描述的版本。
- C++虚拟关键字和系统更新
- 虚拟关键字的偏差
- 将虚拟函数与最终关键字结合使用
- 为什么此指针值在C 中添加虚拟关键字后更改
- 如果多级继承,如何使用虚拟关键字
- 与C++中的虚拟关键字混淆
- 虚拟关键字的使用与C++中的简单重新定义
- 如何调用孩子的方法:虚拟关键字不起作用
- 'override'关键字只是对被覆盖的虚拟方法的检查吗?
- 为什么人们将虚拟关键字放在std :: exception :: what()的面前
- 默认关键字虚拟析构函数
- 在 C++11 中同时使用虚拟关键字和覆盖关键字是否有任何细微之处
- 如何避免虚拟关键字
- 在没有虚拟关键字的情况下实现虚拟函数
- 虚拟析构函数和delete关键字
- 虚拟继承:如果关键字在某个时候被遗忘,会发生什么
- 为什么虚拟关键字会增加派生类的大小
- 虚拟继承:当只有一个基类具有"虚拟"关键字时,为什么它有效?有没有更好的方法?
- 具有 *派生* 类中的函数的虚拟关键字对性能的影响
- 虚拟关键字似乎被忽略了