Skip to main content

Что такое виртуальная функция?

Виртуальная функция - это функция, определенная в суперклассе, которая должна присутствовать в подклассе, чтобы этот подкласс имел полное определение класса. Виртуальные функции основаны на парадигме объектно-ориентированного программирования, называемой виртуальным наследованием, которая чаще всего встречается в C ++ с использованием ключевого слова «virtual». Для определения виртуальной функции необходимы два класса: суперкласс и подкласс. Суперкласс - это место, где функция впервые объявлена ​​и, возможно, определена. Подкласс - это место, где функция определяется или переопределяется в зависимости от того, была ли функция определена в суперклассе.

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

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

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

С другой стороны, виртуальные функции не должны быть определены в подклассе, если они объявлены виртуальными в этом подклассе. Например, можно рассмотреть класс A, который объявляет виртуальную функцию и имеет два подкласса, B и C. Кроме того, можно представить, что класс B имеет подклассы D и E, а подкласс C имеет подклассы F и G.

Все классы от B до G должны иметь определенную виртуальную функцию класса A. Если класс B имеет реализацию функции A, классы D и E не нуждаются в ее переделывании. Возможно, подклассы C должны реализовывать функцию A, но оба они делают что-то другое, поэтому определение функции в самом классе C не будет полезным. В этом случае функция может быть объявлена ​​виртуальной в классе C, и реализация не требуется.

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