Наложение наследования на С++
У меня есть базовый класс следующим образом:
class point //concrete class
{
... //implementation
}
class subpoint : public point //concrete class
{
... //implementation
}
Как мне отбрасывать из точечного объекта в объект подпункта? Я пробовал все три из следующих:
point a;
subpoint* b = dynamic_cast<subpoint*>(&a);
subpoint* b = (subpoint*)a;
subpoint b = (subpoint)a;
Что не так с этими приведениями?
Ответы
Ответ 1
Как мне отбрасывать из объекта точки в объект подпункта?
Вы не можете; если только point
не имеет оператора преобразования, или subpoint
имеет конструктор преобразования, и в этом случае типы объектов могут быть преобразованы без необходимости приведения.
Вы можете использовать ссылку point
(или указатель) на ссылку subpoint
(или указатель), если упомянутый объект действительно имеет тип subpoint
:
subpoint s;
point & a = s;
subpoint & b1 = static_cast<subpoint&>(a);
subpoint & b2 = dynamic_cast<subpoint&>(a);
Первый (static_cast
) более опасен; нет проверки, что преобразование действительно, поэтому, если a
не относится к subpoint
, то использование b1
будет иметь поведение undefined.
Второй (dynamic_cast
) безопаснее, но работает, только если point
является полиморфным (то есть, если он имеет виртуальную функцию). Если a
относится к объекту несовместимого типа, тогда он выдает исключение.
Ответ 2
В первом примере dynamic_cast
работает только в том случае, если в базовом классе есть хотя бы один виртуальный метод. И если объект фактически не относится к типу, который вы пытаетесь выполнить, это приведет к NULL.
Для второго примера вам нужно &a
вместо a
, но как только вы исправили, что получите поведение undefined, потому что тип объекта неверен.
Третий пример требует operator subpoint()
метода в point
для преобразования при создании копии.
Ответ 3
В целом, это не сработает, потому что point
не является subpoint
; верно только обратное. Однако есть и другие проблемы.
В порядке:
subpoint* b = dynamic_cast<subpoint*>(&a);
dynamic_cast
работает только с полиморфными типами, т.е. типами, объявляющими хотя бы одну виртуальную функцию. Я предполагаю, что point
не имеет виртуальных функций, что означает, что он не может использоваться с dynamic_cast
.
subpoint* b = (subpoint*)a;
Для этого приведения point
необходимо объявить оператор преобразования subpoint *
, например, point::operator subpoint *()
.
subpoint b = (subpoint)a;
Для этого приведения в действие нужно указать, что оператор преобразования в subpoint
или subpoint
должен иметь конструктор, который принимает параметр, который можно преобразовать из point
.
Ответ 4
Цель динамического приведения - "проверять во время выполнения, если объект имеет определенный тип в иерархии". Теперь давайте посмотрим, что у вас есть:
- У вас есть точечный объект. Не подпункт.
- Вы запрашиваете динамическое копирование, если объект является подпунктовой. Это не так.
- Поскольку его не подпункт, dynamic_cast терпит неудачу - его способ сказать вам, что объект не тот тип, который вы пытаетесь передать.
В отличие от этого, это сработало бы:
subpoint c;
point *a = &c;
subpoint* b = dynamic_cast<subpoint*>(&a);
subpoint* b = (subpoint*)a;
Ответ 5
a
не может быть превращено в subpoint
. что реализации там нет.
Ответ 6
Что не так с этими приведениями?
Тот факт, что вы пытаетесь сделать это. A point
не является subpoint
, я был бы удивлен, если бы это сработало.