Я думаю, это классика, но в моем случае у меня есть ограничения, которые должны упростить проблему.
Просто я получаю некоторую структуру 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 ...
}
Как мне это сделать ?
Заранее спасибо,
Чарльз
Если вы можете изменить A
Структура вы можете рассмотреть просто добавление этих значений в A
с неинициализированным значением (используя указатель или boost::optional
) и инициализировать их лениво.
В противном случае, если вы не можете изменить A
и не хочу копировать значения из каждого A
в это соответствует B
вы можете рассмотреть возможность B
не вытекают из A
Просто есть дополнительные атрибуты. Тогда вы будете поддерживать глобальный std::map<A*, B>
[1] и найдите дополнительные атрибуты, посмотрев на карту. Если вы выберете этот путь, спросите себя, знаете ли вы, когда удалять устаревшие A
с из map
,
A*
так как вы хотите избежать копирования A
s.Если A — это B с несколькими меньшими атрибутами, то это не B, не так ли? В противном случае мы могли бы привести из любого объекта в мире к любому другому объекту и просто искать атрибуты / методы с одинаковыми именами / сигнатурами.
Но мне пришлось бы спросить, почему вы захотите передать объект, который, как вы знаете, имеет неверный тип. Если метод не нуждается в дополнительных атрибутах, предоставляемых B, измените его сигнатуру на A *, а не B *. И если ему нужны эти значения, вы не можете передать объект, у которого их нет.
Если вы действительно действительно должны это сделать, и я думаю, что вы видите, что я не вижу, что это хороший дизайн, то, возможно, рассмотрите возможность создания статического метода где-нибудь, который принимает A и возвращает новый B с неизвестными атрибутами, установленными в ноль или что-то.