Использование позднего связывания для вызова частного метода из не частного контекста

Я был удивлен выводом кода ниже (g++ 4.4.7).

class A {
public:
virtual void f() {std::cout << "A::f()" << std::endl;}
};

class B : public A {
private:
// Automatically virtual, because of base class
void f() {std::cout << "B::f()" << std::endl;}
};

int main(int argc, const char *argv[])
{
A *pB = new B();
pB->f();
return 0;
}

Выход

B::f()

Я знаю, что из-за позднего связывания компилятор не может выдать ошибку здесь, но почему мы можем вызвать приватный метод из не приватного контекста?

Каково обоснование?

1

Решение

n3376 11.5.1


Правила доступа (пункт 11) для виртуальной функции определяются ее объявлением и не зависят от
правила для функции, которая позже переопределяет ее.


11.5.2


Доступ проверяется в точке вызова с использованием типа выражения, используемого для обозначения объекта, для которого
функция-член вызывается. Доступ функции-члена в классе в
который был определен (D в приведенном выше примере), как правило, не известен.

2

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


Спецификаторы доступа существуют только для целей компиляции. Любая память в пределах выделения вашей программы может быть доступна любой части исполняемого файла; нет общедоступной / частной концепции во время выполнения

Функции позднего связывания выполняются во время выполнения, поэтому нет общедоступной и закрытой концепции для времени выполнения.

1

На самом деле я попытался выполнить этот код с небольшими изменениями, чтобы указать базу
класс виртуальной функции в приватном разделе, и я получил ошибку от компилятора. потому что в компиляции
время первый элемент управления переходит к функции базового класса, но это определено в закрытом разделе, так
ошибка при компиляции. Всякий раз, когда вы объявляете объект производного класса, принимая
ссылка базового класса. Во время компиляции управление переходит в базовый класс первым и каждый класс
создает собственную виртуальную таблицу, а затем во время выполнения объект указателя вызывает производный класс
функция и не имеет значения, где он объявлен частным или публичным, как я уже говорил ранее.

   class A {
virtual void f() {std::cout << "A::f()" << std::endl;}
};

class B : public A {
private:
// Automatically virtual, because of base class
void f() {std::cout << "B::f()" << std::endl;}
};

int main(int argc, const char *argv[])
{
A *pB = new B();
pB->f();
return 0;
}
0
По вопросам рекламы [email protected]