В чем смысл чисто виртуальной функции-члена с телом функции?

К своему изумлению я только что узнал, что это законный C ++

struct A {
  void foo(int) const = 0;  // pure virtual
  // ...
};
void A::foo(int) const { /* ... */ }

Каковы разумные варианты использования для этого? Т.е. когда будет вызван A::foo и почему это правильная / лучшая реализация? Есть ли здесь различия между C ++ 03 и C ++ 11?


Хорошо, был предыдущий вопрос (который я не нашел) с тем же намерением. Однако это было до C ++ 11. Так что мой последний вопрос остается в силе.


person Walter    schedule 27.08.2013    source источник
comment
спасибо, что указали на предыдущий вопрос. Мой поиск не поднял этого. Однако этот вопрос был до C ++ 11. Итак, последняя часть моего вопроса осталась без ответа.   -  person Walter    schedule 27.08.2013
comment
Просто для подтверждения void foo (int) const = 0; Это допустимый способ объявления чистой виртуальной функции даже без виртуального ключевого слова?   -  person Vivek Kumar    schedule 27.08.2013


Ответы (3)


Каковы разумные варианты использования для этого?

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

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

когда A::foo когда-нибудь будет вызван?

Это можно назвать только не виртуальным; Например:

struct B : A {
    void f(int i) const {
        A::foo(i);    // non-virtual call
        // Do the B-specific stuff
    }
};

почему это правильная / лучшая реализация?

Альтернативой было бы придумать новое имя для частичной реализации / реализации по умолчанию в дополнение к нереализованной чистой виртуальной функции.

Есть ли здесь различия между C ++ 03 и C ++ 11?

No.

person Mike Seymour    schedule 27.08.2013
comment
+1, я бы также добавил, что общий вариант использования - это чистый виртуальный деструктор, который иногда используется для принудительного создания производных типов, но он должен иметь определение, поскольку производный тип должен вызывать базовый деструктор. - person David Rodríguez - dribeas; 27.08.2013
comment
@ DavidRodríguez-dribeas: Хорошее замечание, я добавил примечание об этом. - person Mike Seymour; 27.08.2013

Канонический вариант использования - пометить класс как абстрактный, предоставив чисто виртуальный деструктор, который ДОЛЖЕН иметь реализацию.

Это было правилом еще до C ++ 98.

person SteveLove    schedule 27.08.2013
comment
Гм - реализация == с телом, разве нет? - person SteveLove; 27.08.2013
comment
@MikeSeymour: Он говорит не о какой-либо функции, а о деструкторе, который должен быть определен. - person David Rodríguez - dribeas; 27.08.2013
comment
Извините, я неправильно прочитал ответ. +1. - person Mike Seymour; 27.08.2013

Конечно, это законно. Под чистыми виртуальными функциями подразумеваются тот экземпляр того класса, в котором он объявлен, не может быть создан, а не то, что он не может иметь реализации.
Это похоже на интерфейс в C #, например .

Какие возможности он предоставляет?
1. клиент может использовать реализацию по умолчанию.
2. классы с чистым виртуальным деструктором больше не вызывают ошибку компоновщика (когда вы применяете удаление к указателю на базовый класс: вызываются деструкторы производного класса, а после этого вызывается деструктор базового класса, если вы опускаете реализацию - компоновщик выдаст ошибку).

Ссылки: необходимость реализации чисто виртуального метода подробно описана в книге Скотта Майерса «Эффективный C ++».

person spin_eight    schedule 27.08.2013