В чем разница между экземплярами виртуальных функций в C ++? - PullRequest
1 голос
/ 14 сентября 2009

В чем разница между следующими двумя объявлениями?

virtual void calculateBase() = 0;  
virtual void calculateBase();

Я прочитал, что первая (= 0) - "чисто абстрактная функция", но что это делает второй?

Ответы [ 8 ]

8 голосов
/ 14 сентября 2009

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

  • шаблонный метод шаблон проектирования, где базовый класс реализует структуру вокруг вызова функции, но детали вызова функции должны заполняться производным классом, и
  • Шаблон проектирования "интерфейс", потому что в C ++ нет ключевого слова интерфейса. Абстрактные базовые классы, в идеале только с чисто виртуальными функциями и без данных-членов, являются способом определения интерфейсов в C ++.

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

7 голосов
/ 14 сентября 2009

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

Вторая - это виртуальная функция (то есть «нормальная» виртуальная функция). Класс обеспечивает реализацию для этой функции, но его производный класс может переопределить эту реализацию, предоставив собственную реализацию для этого метода.

4 голосов
/ 14 сентября 2009

Первый не обязательно должен быть реализован в базовом классе, но требует его реализации в унаследованных классах.

Вы должны реализовать второй в базовом классе, и он может быть реализован в унаследованных классах.

3 голосов
/ 14 сентября 2009

Как правило, при наследовании вы вынуждены переопределять первый, и разрешено переопределять второй.

Исходя из Java, не так ли?

1 голос
/ 14 сентября 2009

virtual void CalculateBase () = 0;

Первая функция - это виртуальная функция Pure, реализация которой не может быть выполнена в классе и действует как чистый абстрактный класс или интерфейсный класс. Конкретная реализация должна быть сделана или переопределена в подклассе. Он действует как интерфейсный класс для своих производных классов.

virtual void CalculateBase ();

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

1 голос
/ 14 сентября 2009

Я думаю, что вы смешиваете термины ...

virtual void x() = 0;

- это чисто виртуальная функция или абстрактная функция. Это виртуальная функция без реализации. Вы говорите о чистом абстрактном классе, который является эквивалентом интерфейса на языке c ++, о классе, имеющем только абстрактные функции.

virtual void x();

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

0 голосов
/ 14 сентября 2009

на Java

virtual void calculateBase() = 0;  

будет

abstract void calculateBase();

и

virtual void calculateBase();

будет

void calculateBase();

Чтобы быть совершенно ясным,

void calculateBase();

в C ++ "совпадает" с

final void calculateBase();

на Java. То есть final - это "default" в C ++. Однако есть исключение из этого правила. При создании подкласса класса с помощью виртуального метода и его повторной реализации без использования виртуального ключевого слова метод в подклассе не будет окончательным.

0 голосов
/ 14 сентября 2009

Вторая функция должна иметь реализацию в классе, который ее объявляет (отсутствие '= 0'), и может быть переопределено подклассами.

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

...