Наследование и указатели базового класса

Я проходил через это Книга и я не могу обернуть голову вокруг этого:

если 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();
}

1

Решение

если 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 или какой-то неизвестный производный класс.

1

Другие решения

Было бы ошибкой, если бы вы попытались позвонить f() из сферы B, Но вы вызываете его через указатель на базовый класс. Поиск имени и разрешение перегрузки выполняется на основе статического типа объекта, A* в этом случае. Оттуда, f() виден

2

Вызов pa1-> f (); сначала направляется на объект типа A, так как pa1 является указателем на этот тип. Виртуальное ключевое слово перенаправило бы вызов на тип B, если бы была функция, которая соответствует точной (!!) подписи вызова. Поскольку в типе B такой функции нет, выполняется функция типа A.

Я имею в виду, что в этом случае функции не «скрывают» друг друга, потому что подпись отличается. [f (void) против f (int)]

РЕДАКТИРОВАТЬ:
Чтобы быть более понятным. f (int) и f (void) — две совершенно разные функции. Как отличается от f (void) до g (int).

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector