Какие недостатки у "апскейтинга"? - PullRequest
3 голосов
/ 08 ноября 2011

Цель абстрактного класса - не позволить разработчикам создать объект базового класса, а затем upcast it, AFAIK.

Теперь, даже если upcasting не требуется, и я все еще использую это, оказывается ли это "невыгодным" в некотором роде?

Дополнительные разъяснения:
Из Мышления в C ++:

Часто в дизайне требуется, чтобы базовый класс представлял только интерфейс для своих производных классов.То есть вы не хотите, чтобы кто-либо на самом деле создавал объект базового класса, а только обновлял его, чтобы можно было использовать его интерфейс.Это достигается путем превращения этого класса в абстрактный,

Под апгрейдом я подразумевал: baseClass *obj = new derived ();

Ответы [ 4 ]

4 голосов
/ 08 ноября 2011

Upcasting может быть невыгодным для неполиморфных классов.Например:

class Fruit { ... };  // doesn't contain any virtual method
class Apple : public Fruit { ... };
class Blackberry : public Fruit { ... };

куда-то прогнать,

Fruit *p = new Apple;  // oops, information gone

Теперь вы никогда не узнаете (без какого-либо ручного механизма), что если *p является экземпляром Appleили Blackberry.

[Обратите внимание, что dynamic_cast<> недопустимо для неполиморфных классов.]

2 голосов
/ 08 ноября 2011

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

Рассмотрим класс Animal.Не имеет смысла создавать экземпляр этого класса, потому что нет ничего, что является просто животным.Есть утки, собаки и слоны, каждый из которых является подклассом животных.Формально объявив класс животных, вы можете уловить сходства всех типов животных, а сделав его абстрактным, вы можете выразить невозможность его создания.

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

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

0 голосов
/ 08 ноября 2011

Upcasting - это технический инструмент.

Как и любой инструмент, он полезен при правильном использовании и опасен / невыгоден при непоследовательном использовании.

Это может быть хорошо или плохо в зависимости от того, насколько «чистым» вы хотите, чтобы ваш код соответствовал заданной парадигме программирования.

Теперь C ++ не обязательно является «чистым ООП», не обязательно «чистым универсальным», не обязательно «чистым функционалом». А поскольку C ++ является «прагматичным языком», в общем случае преимущество не в том, чтобы он соответствовал «единственной парадигме».

Единственное, что можно сказать технически, это то, что

  • Производный класс - это базовый класс плюс нечто большее
  • Обращение к производному через базовый указатель делает это «что-то большее» недоступным, если в базе нет механизма, позволяющего вам перейти в производную область.
  • Механизм, который C ++ предлагает для этого неявный переход - это виртуальные функции.
  • Механизм, который C ++ предлагает для явного перехода , равен dynamic_cast (используется при понижении рейтинга).
  • Для неполиморфных объектов (у которых нет виртуальных методов) static_cast (для downcast) все еще доступно, но без проверки во время выполнения.

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

0 голосов
/ 08 ноября 2011

Одним из недостатков была бы очевидная потеря новой функциональности, введенной в производном классе:

class A
{
   void foo();
}

class B : public A
{
   void foo2();
}

A* b = new B;
b->foo2(); //error - no longer visible

Я говорю здесь о не виртуальных функциях.

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

Однако все это можно избежать с помощью хорошей архитектуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...