наследование — C ++: расширение объекта путем понижения класса до производного класса

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

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

Теперь, когда я вызываю метод, который ожидает B, но я кормлю его A, компилятор не рад: объекты могут не быть B, как все кошки не львы.

Но в моем случае, я клянусь, что все As являются B, хотя и с меньшими атрибутами. Атрибуты, которые не найдены, могут быть указаны как неинициализированные, это нормально, я также клянусь, что никогда не вызову атрибут до его инициализации. По сути, первое, что я делаю при получении объектов A в качестве входных данных, это заполнение оставшихся атрибутов B, которые рассчитываются на основе атрибутов A. Я просто не хочу делать копии As, когда попадаю в B, просто чтобы добавить несколько атрибутов, потому что тогда атрибуты As будут скопированы в память. Я не собираюсь когда-либо модифицировать эти исходные атрибуты A, я просто буду использовать их для вычисления производных атрибутов, а затем расскажу и поработаю над объектами B с атрибутами A и производными атрибутами.

Пример :

Из общего заголовка проекта:

struct Rectangle {
// Side lengths
int a,b;
}

Из локального заголовка:

struct LocalRectangle : Rectangle {
int area;
}

void updateModule(Rectangle inputRect);

Из местного источника:

void updateModule(Rectangle inputRect) {
LocalRectangle r = (LocalRectangle)inputRect;
r.area = r.a*r.b;
// More processing ...
}

Как мне это сделать ?

Заранее спасибо,

Чарльз

1

Решение

Если вы можете изменить A Структура вы можете рассмотреть просто добавление этих значений в A с неинициализированным значением (используя указатель или boost::optional) и инициализировать их лениво.

В противном случае, если вы не можете изменить A и не хочу копировать значения из каждого A в это соответствует B вы можете рассмотреть возможность B не вытекают из AПросто есть дополнительные атрибуты. Тогда вы будете поддерживать глобальный std::map<A*, B>[1] и найдите дополнительные атрибуты, посмотрев на карту. Если вы выберете этот путь, спросите себя, знаете ли вы, когда удалять устаревшие Aс из map,


  1. я использую A* так как вы хотите избежать копирования As.
1

Другие решения

Если A — это B с несколькими меньшими атрибутами, то это не B, не так ли? В противном случае мы могли бы привести из любого объекта в мире к любому другому объекту и просто искать атрибуты / методы с одинаковыми именами / сигнатурами.

Но мне пришлось бы спросить, почему вы захотите передать объект, который, как вы знаете, имеет неверный тип. Если метод не нуждается в дополнительных атрибутах, предоставляемых B, измените его сигнатуру на A *, а не B *. И если ему нужны эти значения, вы не можете передать объект, у которого их нет.

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

1

По вопросам рекламы [email protected]