基类的继承和指针

Inheritance and Pointers of Base Class

本文关键字:指针 继承 基类      更新时间:2023-10-16

我正在阅读这本书,我无法理解这一点:

如果B::f(int)隐藏A::f(),为什么pa1->f();不给出错误?

名称隐藏不是意味着,f()函数class B中不存在吗?如果pa1指向class B的对象,那么pa1->f();应该像b.f()一样导致错误!

请解释一下,因为我无法通过这本书理解它!提前感谢!

#include <iostream>
using namespace std;
struct A {
   virtual void f() { cout << "Class A" << endl; }
};
struct B: A {
   void f(int) { cout << "Class B" << endl; }
};
struct C: B {
   void f() { cout << "Class C" << endl; }
};
int main() {
   B b; C c;
   A* pa1 = &b;
   A* pa2 = &c;
//   b.f();
   pa1->f();
   pa2->f();
}

如果您尝试从B范围内调用f(),那将是一个错误。但是,您是通过指向基类的指针调用它的。名称查找和重载解析是根据对象的静态类型完成的,在本例中A*。从那里,f()可见。

如果B::f(int)隐藏A::f(),为什么pa1->f();不给出错误?

因为pa1指向A,而A有一个叫做f的成员,可以这样称呼。在这种情况下,任何其他类(包括B)都是无关紧要的。

名称隐藏不是意味着,f()函数B中不存在吗?

不。这意味着,在B的上下文中,唯一可以通过非限定查找找到的称为f的函数是B::f。它不会从任何其他上下文中删除f,也不会阻止合格的查找(如 b.A::f() )找到它。

如果pa1指向类 B 的对象,那么pa1->f();应该像b.f()一样导致错误!

动态类型是 B ,因此这是用于调用函数的类型(在运行时)。非虚函数由编译器根据静态类型选择,即A 。通常,编译器不知道动态类型;它只知道指针指向一个A或某个未知的派生类。

调用 pa1->f(); 首先路由到类型 A 的对象,因为 pa1 是指向该类型的指针。如果存在与调用的确切 (!!) 签名匹配的函数,则 virtual 关键字会将调用重新路由到类型 B。由于类型 B 中没有这样的函数,因此执行类型 A 函数。

我的意思是,在这种情况下,函数不会因为签名不同而相互"隐藏"。[f(无效) vs. f(int)]

编辑:更清楚一点。f(int) 和 f(void) 是两个完全不同的函数。与 f(void) 到 g(int) 一样不同。