2013-04-03 2 views
1

знаменитая статья Герба Саттера Virtuality, говорится следующее:C++ Почему я могу вызвать частную виртуальную функцию базового класса из drived класса?

Руководство # 2: Предпочитаю делать виртуальные функции частных.

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

В приведенном ниже коде private_base_func() является частной виртуальной функцией, объявленной в базовом классе и вызываемой в drived class constructor, Strangely, этот код компилируется отлично, и он вызывает частную виртуальную функцию базового класса из drived класса, который противоречит сказанному выше. Это меня очень смущает.

class base 
{ 
public: 

    base() {} 
    virtual ~base(){} 

private: 
    virtual void private_base_func() 
    { 
     std::cout << "Base Class invoke" << std::endl; 
    } 

}; 


class drived : public base 
{ 
public: 
    drived() 
    { 
     private_base_func(); // this line should not compile 
    } 

private: 
    // Overriding base class virtual function 
    void private_base_func() 
    { 
     std::cout << "Drived class invoke" << std::endl; 
    } 
}; 

int main() 
{ 
    base* ptr = new drived(); 
    return 0; 
} 

Спасибо авансов за ваш ответ

ответ

8

Это потому, что вы вызываете версию drived «s из private_base_func, которая, конечно, доступных в drived. Функция, которую вы не можете назвать это версия base «S:

drived() 
{ 
    base::private_base_func(); // this line will not compile 
} 
1
private_base_func(); // this line should not compile 

Как так? private_base_func - это функция private в drived, и эта линия находится внутри drived, поэтому вполне нормально ее называть. Обратите внимание, что это отличается от:

drived() 
{ 
    base b; 
    b.private_base_func(); // this line does not compile 
} 

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

Смежные вопросы