Производный класс Вызывается закрытый метод

У меня есть указатель базового класса, указывающий на объект производного класса. Метод foo() является общедоступным в базовом классе, но закрытым в производном классе. Базовый класс foo() является виртуальным. Поэтому, когда я вызываю foo() из указателя базового класса, Vptr Table имеет адрес производного класса foo(), НО его private в классе Derived... так как он вызывается.??

Я понимаю полиморфизм во время выполнения, а также понимаю, что спецификаторы Access работают во время компиляции, а концепция Virtual работает во время выполнения. Так что не должно быть ошибки компилятора.

Мой вопрос: это дыра в петле, через которую мы можем вызывать закрытые методы класса Derived? или ожидается, что он будет вести себя таким образом. Любое хорошее объяснение этого поведения.

Заранее большое спасибо.

КОД:

class A
{
public:
    virtual void foo()
    {
        std::cout << "In A";
    }
};


class B:public A
{
private:
    void foo()
    {
       std::cout << "In B ??? Its Private Method :-( ";
    }
};

int main()
{
    A* ptr = new B();
    ptr->foo();
    return 0;
}

2 ответа

Решение

Это приватный метод, но поскольку он виртуальный, его можно вызвать.

N3690 11,5/1

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

Почему это? поскольку

N3690 11,5/2

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

Уровень доступа - это концепция времени компиляции. Среда выполнения не знает, был ли объявлен метод private или же public, Это для вашего удобства.

На самом деле это хороший стандарт кодирования - virtual метод должен быть в идеале public в базовом классе и private или же protected в производных классах. Это заставит вызывающую сторону использовать интерфейсы, а не фактические типы (конечно, это не всегда практично, но полезно принимать во внимание).

Конкретный тип абстрагируется в вашем случае, как и должно быть. Базовый метод объявлен public и вы вызываете его через указатель на базу, так что это разрешено.

Другие вопросы по тегам