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

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

Я понимаю полиморфизм времени выполнения, а также понимаю, что спецификаторы доступа работают во время компиляции, а концепция 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;
}

person Biraj Borah    schedule 09.12.2013    source источник


Ответы (2)


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

n3690 11.5/1

The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it.

Почему это? С

n3690 11.5/2

Access is checked at the call point using the type of the expression used to denote the object for which the member function is called (B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.

person ForEveR    schedule 09.12.2013

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

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

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

person Luchian Grigore    schedule 09.12.2013
comment
[private - это] хороший стандарт кодирования [но] не всегда практичен, это часто нежелательно, когда это целесообразно - во многих ситуациях, когда оптимизатор знает фактический статический тип, может позволить встраивание виртуальных функций, устранение ветвей мертвого кода и т. д. - person Tony Delroy; 09.12.2013