Может ли класс оставаться чисто абстрактным, если у него есть нечистый деструктор?

Я работаю над упражнением, которое просит меня взять базовый класс Rodent и сделать его чистым абстрактным классом. Мое понимание чистого абстрактного класса заключается в том, что он действует как интерфейс и содержит только чистые виртуальные функции. Хотя это простое упражнение, у меня есть проблема с решением, предложенным в книге:

class Rodent
{
    public:

    virtual ~Rodent() {cout << "Destroy rodent" << endl;}
    virtual void run() = 0;
    virtual void squeak() = 0;
};

Как видите, автор добавил фиктивное определение деструктора. Не означает ли добавление этого определения, что это абстрактный класс, а не «чистый» абстрактный класс?


person Bap Johnston    schedule 28.09.2011    source источник
comment
Я понимаю, я хотел знать, является ли это все еще «чистой» абстракцией.   -  person Bap Johnston    schedule 28.09.2011
comment
Наименее интересной частью вопроса является тот факт, что чистый абстрактный класс не является концепцией C++, поэтому он будет сильно зависеть от вашего определения этого термина (сравните с: чистая виртуальная функция которое определено в стандарте как имеющее точное значение)   -  person David Rodríguez - dribeas    schedule 28.09.2011


Ответы (6)


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

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

Вы не можете создавать какие-либо объекты этого класса.

РЕДАКТИРОВАТЬ:

Чистый абстрактный класс — это класс, который имеет исключительно чистые виртуальные функции (и не содержит данных). Поскольку ваш деструктор не является чисто виртуальным, ваш класс не является чистым абстрактным классом.

person Alok Save    schedule 28.09.2011
comment
Я согласен с вами, что это все еще абстрактный класс, ваше определение довольно полное, но для завершения: виртуальная функция называется чистой, когда у нее нет определения, если у нее есть определение, это просто виртуальная функция (на самом деле метод) . Спасибо! - person thamurath; 28.09.2011
comment
Да, чисто виртуальные функции могут иметь определения, но деструктор в этом примере не чистый. Вопрос не в том, является ли класс абстрактным. Речь идет о том, является ли он чистым абстрактным. - person Rob Kennedy; 28.09.2011
comment
@thamurath: это неправильно. Чистые виртуальные функции могут иметь определение, просто C++ не позволяет встраивать определение в класс. Наличие или отсутствие определения функции не меняет того факта, является ли функция чисто виртуальной или нет. - person Alok Save; 28.09.2011
comment
Речь идет о чистых абстрактных классах, а не о чистых виртуальных функциях или абстрактных классах. - person Nemo; 28.09.2011
comment
@Als OP спросил о ЧИСТОЙ абстракции, а не только об абстракции. - person MGZero; 28.09.2011
comment
@thamurath: Это не совсем так. Функция-член является чисто виртуальной, если она объявлена ​​с помощью чистого спецификатора = 0. Разница с вашим определением заключается в том, что чисто виртуальная функция может иметь определение: struct test { virtual void f() = 0; }; void test::f() {} — это вполне допустимый (и пригодный для использования) код. Это не просто виртуальная функция, так как наличие f в test запрещает создание экземпляров объектов типа test, что и означает чистая виртуальная. - person David Rodríguez - dribeas; 28.09.2011

Деструктор требуется для каждого класса по правилам C++. Если вы его не предоставите, компилятор сгенерирует его за вас.

На мой взгляд, это все еще чистый абстрактный класс, потому что деструктор является исключением из правил.

person Mark Ransom    schedule 28.09.2011
comment
Что делать, если деструктор устанавливает глобальную переменную? Что делать, если конструктор открывает файл для регистрации? Конечно, это очень глупый вопрос об определениях, но в этом контексте я не уверен, что согласен с вами :-) - person Nemo; 28.09.2011
comment
@Nemo: это исключительно вопрос того, что, по вашему мнению, должен подразумевать чистый абстрактный класс. Если вы хотите использовать этот термин для обозначения классов, которые (в дополнение к другим ограничениям) имеют деструкторы бездействия, то определите его таким образом. Марк и автор учебника для вопрошающих определяют это по-другому. В написании книги замечательно то, что вы можете сказать, что означают технические термины в ней :-) - person Steve Jessop; 28.09.2011
comment
Что плохого в том, что все члены являются чисто виртуальными функциями? - person JoeG; 30.09.2011
comment
@JoeGauterin, деструктор является членом, и он не может быть чисто виртуальным, потому что правила C ++ не позволяют этого. В остальном ваше определение великолепно. - person Mark Ransom; 30.09.2011
comment
@Mark Ransom: деструкторы могут быть чисто виртуальными - struct foo{ virtual ~foo()=0;}; inline foo::~foo(){} - person JoeG; 30.09.2011

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

Обычно вы ожидаете, что он будет пустым:

class Rodent {
public:
  virtual ~Rodent() {}
  virtual void run() = 0;
  virtual void squeak() = 0;
};

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

Я не думаю, что вы кого-то смутите, назвав свой чисто виртуальным.

person Tom Kerr    schedule 28.09.2011
comment
Пустое тело деструктора полезно, потому что оно будет вызываться всеми производными классами; если известно, что он пуст во время компиляции, компилятор может его оптимизировать. - person Mark Ransom; 28.09.2011
comment
@MarkRansom Я понимаю, почему это хорошо, полезно и т. Д. Есть ли строгое определение в соответствии со спецификацией - это одно, и у меня нет ответа на этот вопрос. Я не думаю, что есть концептуальная разница между двумя с точки зрения понимания того, что происходит. - person Tom Kerr; 28.09.2011

Насколько я понимаю, стандарт C++ не определяет чистый абстрактный класс. Однако C++0x (n3290) определяет абстрактный класс.

10.4/2 Класс является абстрактным, если он имеет хотя бы одну чисто виртуальную функцию.

чистый абстрактный класс — это общепринятый термин, описывающий абстрактный класс, который;

  • не имеет элементов данных
  • не имеет каких-либо нечистых виртуальных функций
  • не имеет каких-либо конкретных функций

указывается пользователем.

Итак, согласно этому соглашению, class Rodent не является чистым абстрактным классом.

person mloskot    schedule 28.09.2011

Подумайте о том, чтобы реализовать свой интерфейс так

class Rodent {
public:
  virtual ~Rodent() = 0;
  virtual void run() = 0;
  virtual void squeak() = 0;
};
inline Rodent::~Rodent() {}

Указание вашего деструктора как чисто виртуального и встраивание реализации позволяет избежать следующего предупреждения в MSVC2010 при экспорте подклассов:

warning C4275: non dll-interface class 'A' used as base for dll-interface class 'B'
person Jesse Stimpson    schedule 28.09.2011

Да, это уже не чистый класс. Чистый абстрактный класс не имеет в себе никакой функциональности, он просто обеспечивает структуру. cout — это функциональность.

person Craig    schedule 28.09.2011