Я был удивлен выводом кода ниже (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()
Я знаю, что из-за позднего связывания компилятор не может выдать ошибку здесь, но почему мы можем вызвать приватный метод из не приватного контекста?
Каково обоснование?
n3376 11.5.1
Правила доступа (пункт 11) для виртуальной функции определяются ее объявлением и не зависят от
правила для функции, которая позже переопределяет ее.
Доступ проверяется в точке вызова с использованием типа выражения, используемого для обозначения объекта, для которого
функция-член вызывается. Доступ функции-члена в классе в
который был определен (D в приведенном выше примере), как правило, не известен.
Спецификаторы доступа существуют только для целей компиляции. Любая память в пределах выделения вашей программы может быть доступна любой части исполняемого файла; нет общедоступной / частной концепции во время выполнения
Функции позднего связывания выполняются во время выполнения, поэтому нет общедоступной и закрытой концепции для времени выполнения.
На самом деле я попытался выполнить этот код с небольшими изменениями, чтобы указать базу
класс виртуальной функции в приватном разделе, и я получил ошибку от компилятора. потому что в компиляции
время первый элемент управления переходит к функции базового класса, но это определено в закрытом разделе, так
ошибка при компиляции. Всякий раз, когда вы объявляете объект производного класса, принимая
ссылка базового класса. Во время компиляции управление переходит в базовый класс первым и каждый класс
создает собственную виртуальную таблицу, а затем во время выполнения объект указателя вызывает производный класс
функция и не имеет значения, где он объявлен частным или публичным, как я уже говорил ранее.
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;
}